Reputation: 660
I have a form with several fields.
To handle the state I am using controlled components.
The approach I used is shown below.
This used to work Initially , but as the requirement changed I had to use nested Object in defining the initial state.
The handleChange
no more works properly .
How can I achieve the same result for nested Object too.
const [details, setDetails] = useState({
description: null,
platform: "Xbox",
region: "ASIA",
time:{
start: "2017-05-24T10:30",
end: "2017-05-28T10:30",
},
contact: {
email: "",
phone: "",
twitter: "",
discord: "",
}
});
function handleChange(evt) {
const value = evt.target.value;
setDetails({
...details,
[evt.target.name]: value,
});
}
Sample components
<TextField
label="Description"
onChange={handleChange}
name="description"
value={details.description}
/>
<TextField
label="email"
onChange={handleChange}
name="email"
value={details.contact.email}
/>
Upvotes: 0
Views: 306
Reputation: 1742
I think this would work the best.
function handleNestedChange(evt) {
const value = evt.target.value;
const keys = evt.target.name.split(".");
if(keys > 1){
setDetails({
...details,
[keys[0]]: {
...details[keys[0]],
[keys[1]]: event.target.value
}
});
}else{
setDetails({
...details,
[keys[0]]: event.target.value
}
});
}
}
<TextField
label="Email"
onChange={handleChange}
name="contact.email"
value={details.description}
/>
also if you ever start storing huge nested objects into state take a look at the package immutability-helper. Its makes it easier to update only specific fields in a object and does it much faster then recreating the whole thing.
Upvotes: 2
Reputation: 925
You can update nested object like this
<TextField
label="email"
onChange={handleChange}
name="contact_email"
value={details.contact.email}
/>
function handleChange(evt) {
const value = evt.target.value;
const name = evt.target.name.split("_"); // [0: contact, 1: email]
setDetails({ ...details, amount : { ...details[name[0]],
[name[1]]: value }})
}
Upvotes: 0
Reputation: 1679
Lazy way but I will do something like that:
function handleNestedChange(key, event) {
setDetails({
...details,
[key]: {
...details[key],
[event.target.name]: event.target.value
}
});
}
<TextField
label="email"
onChange={(e) => handleNestedChange("contact", e)}
name="email"
value={details.contact.email}
/>
Upvotes: 0
Reputation: 12807
Need orther handleChange
for fileds in contact
:
function handleChangeContact(evt) {
const value = evt.target.value;
setDetails({
...details,
contact: {
...details.contact,
[evt.target.name]: value,
}
});
}
<TextField
label="email"
onChange={handleChangeContact}
name="email"
value={details.contact.email}
/>
Upvotes: 0