I'm trying to update a single key/value pair in a user object which contains another array of object called "education". I set a custom attribute called "index" on the list components to access the array index when updating.
// User object
const [userData, setUserData] = useState({
firstName: '',
lastName: '',
title: '',
email: '',
phoneNumber: '',
website: '',
bio: '',
education: [
{
id: uniqid(),
school: '',
degree: '',
city: '',
state: '',
timeframe: ''
}
]
})
// Render input form for Education
const listItems = props.userData.education.map((user, index) => {
return (
<div key={index}>
<h2>University/School #{index}</h2>
<input
type="text"
index={index}
placeholder="Your school"
name="school"
onChange={props.handleChange}
value={props.userData.education[index].school}
/>
</div>
);
});
Created this fucntion handler for onChange but it just returns an empty string and doesn't update the object. I feel i'm using the spread operator here wrongly but can't figure out how to put all together rightly.
// Update user education state
const handleChange = (e) => {
const { value, name } = e.target
const index = e.target.getAttribute('index')
setUserData(prevUser => ({
...prevUser,
[prevUser.education[index]]: {
[name]: value
}
}))
}
CodePudding user response:
You don't need to add a custom index value and get it off an attribute. You can add it to your change callback:
const listItems = props.userData.education.map((user, index) => {
return (
<div key={index}>
<h2>University/School #{index}</h2>
<input
type="text"
index={index}
placeholder="Your school"
name="school"
onChange={(e) => props.handleChange(e, index)}
value={props.userData.education[index].school}
/>
</div>
);
});
if you run console.log
inside your handleChange
what do you see for value
and name
?
I am hoping you can learn a bit about how to debug your code.
const handleChange = (e, index) => {
const { value, name } = e.target
console.log({value});
console.log({name});
setUserData(prevUser => {
const newItem = {
[prevUser.education[index]]: {
[name]: value
}
}
console.log({newItem}); // is this what you expect?
return ({
...prevUser,
...newItem,
})))
}
Finally, your value
should come from state
directly, not Props. I am assuming your state is inside the same component as your rendering? Otherwise, are you passing state as a prop to your consuming component?
As for your spread, yes, you are missing a little.
const newItem = {
[prevUser.education[index]]: {
...[prevUser.education[index]], // without this you will overwrite all the previous data
[name]: value
}
}