在表单中使用嵌套对象更新状态
Update state with Nested object in Form
我在尝试使用 useState 更新嵌套对象时遇到了一些问题。我有一个表格,用户可以在其中 add/edit 汽车信息。所以基本上我是在本地状态下处理汽车,以表格形式显示数据。
//Local state to handle a Car
const [car, setCar] = useState({
brand: "Mazda",
vin: "JMB838783S",
location: {
address: "9098 West Alabama Street",
lat: "-22.73984",
long: "8.44538",
},
contact: {
phone: "+16758907676",
email: "car@provider.com",
}
});
然而,当我尝试编辑地址或 phone 的信息时,我无法使用 onChange
中的函数使其工作
const handleInputChanges = e => {
setCar({
...car,
[e.target.name] : e.target.value
})
};
表格
<FormContainer onSubmit={handleSubmit}>
<DropPictureZone onImageDropped={setThumbnailDropped} />
<InputText
type="text"
name="brand"
placeholder="Brand"
value={name}
onChange={handleInputChanges}
/>
<InputText
type="text"
name="address"
placeholder="Address"
value={location.address}
onChange={handleInputChanges}
/>
<div className="p-grid">
<div className="p-col">
<InputText
type="text"
name="lat"
placeholder="Latitude"
value={location.lat}
onChange={handleInputChanges}
/>
</div>
<div className="p-grid">
<div className="p-col-4">
<InputMask
mask="(xxx)-xxx-xxxx"
name="phone"
placeholder="Phone Number"
value={contact.phone}
onChange={handleInputChanges}
/>
</div>
<div className="p-col">
<InputText
type="text"
name="email"
placeholder="Email"
value={contact.email}
onChange={handleInputChanges}
/>
</div>
</div>
<Button label="Save" />
</FormContainer>
实现这一目标的正确方法是什么?
谢谢。
这个问题有很多正确答案。这是一个:
修改您的更改处理程序以接受一个 curried 参数,通知它要更新哪个嵌套对象。
新的处理程序看起来像这样:
const handleInputChanges = level => e => {
if (!level) {
// Assume root level
setCar({
...car,
[e.target.name] : e.target.value
})
} else {
setCar({
...car,
[level]: {
...car[level],
[e.target.name] : e.target.value
}
})
}
};
然后像这样修改你的表单:
<InputText
type="text"
name="brand"
placeholder="Brand"
value={name}
onChange={handleInputChanges()} // Root level
/>
<InputText
type="text"
name="address"
placeholder="Address"
value={location.address}
onChange={handleInputChanges('location')} // location object
/>
<InputMask
mask="(xxx)-xxx-xxxx"
name="phone"
placeholder="Phone Number"
value={contact.phone}
onChange={handleInputChanges('contact')} // contact object
/>
这只是每种类型的示例,您需要修改每个字段。
我在尝试使用 useState 更新嵌套对象时遇到了一些问题。我有一个表格,用户可以在其中 add/edit 汽车信息。所以基本上我是在本地状态下处理汽车,以表格形式显示数据。
//Local state to handle a Car
const [car, setCar] = useState({
brand: "Mazda",
vin: "JMB838783S",
location: {
address: "9098 West Alabama Street",
lat: "-22.73984",
long: "8.44538",
},
contact: {
phone: "+16758907676",
email: "car@provider.com",
}
});
然而,当我尝试编辑地址或 phone 的信息时,我无法使用 onChange
中的函数使其工作const handleInputChanges = e => {
setCar({
...car,
[e.target.name] : e.target.value
})
};
表格
<FormContainer onSubmit={handleSubmit}>
<DropPictureZone onImageDropped={setThumbnailDropped} />
<InputText
type="text"
name="brand"
placeholder="Brand"
value={name}
onChange={handleInputChanges}
/>
<InputText
type="text"
name="address"
placeholder="Address"
value={location.address}
onChange={handleInputChanges}
/>
<div className="p-grid">
<div className="p-col">
<InputText
type="text"
name="lat"
placeholder="Latitude"
value={location.lat}
onChange={handleInputChanges}
/>
</div>
<div className="p-grid">
<div className="p-col-4">
<InputMask
mask="(xxx)-xxx-xxxx"
name="phone"
placeholder="Phone Number"
value={contact.phone}
onChange={handleInputChanges}
/>
</div>
<div className="p-col">
<InputText
type="text"
name="email"
placeholder="Email"
value={contact.email}
onChange={handleInputChanges}
/>
</div>
</div>
<Button label="Save" />
</FormContainer>
实现这一目标的正确方法是什么? 谢谢。
这个问题有很多正确答案。这是一个:
修改您的更改处理程序以接受一个 curried 参数,通知它要更新哪个嵌套对象。
新的处理程序看起来像这样:
const handleInputChanges = level => e => {
if (!level) {
// Assume root level
setCar({
...car,
[e.target.name] : e.target.value
})
} else {
setCar({
...car,
[level]: {
...car[level],
[e.target.name] : e.target.value
}
})
}
};
然后像这样修改你的表单:
<InputText
type="text"
name="brand"
placeholder="Brand"
value={name}
onChange={handleInputChanges()} // Root level
/>
<InputText
type="text"
name="address"
placeholder="Address"
value={location.address}
onChange={handleInputChanges('location')} // location object
/>
<InputMask
mask="(xxx)-xxx-xxxx"
name="phone"
placeholder="Phone Number"
value={contact.phone}
onChange={handleInputChanges('contact')} // contact object
/>
这只是每种类型的示例,您需要修改每个字段。