I have retrieved datas stored using useState in an array of object, the datas was then outputted into form fields. And now I want to be able to update the fields (state) as
Here is how you do it:
// sample datas structure
/* const datas = [
{
id: 1,
name: 'john',
gender: 'm'
}
{
id: 2,
name: 'mary',
gender: 'f'
}
] */ // make sure to set the default value in the useState call (I already fixed it)
const [datas, setDatas] = useState([
{
id: 1,
name: 'john',
gender: 'm'
}
{
id: 2,
name: 'mary',
gender: 'f'
}
]);
const updateFieldChanged = index => e => {
console.log('index: ' + index);
console.log('property name: '+ e.target.name);
let newArr = [...datas]; // copying the old datas array
newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to
setDatas(newArr); // ??
}
return (
<React.Fragment>
{ datas.map( (data, index) => {
<li key={data.name}>
<input type="text" name="name" value={data.name} onChange={updateFieldChanged(index)} />
</li>
})
}
</React.Fragment>
)
This is what I do:
const [datas, setDatas] = useState([
{
id: 1,
name: "john",
gender: "m",
},
{
id: 2,
name: "mary",
gender: "f",
},
]);
const updateFieldChanged = (name, index) => (event) => {
let newArr = datas.map((item, i) => {
if (index == i) {
return { ...item, [name]: event.target.value };
} else {
return item;
}
});
setDatas(newArr);
};
return (
<React.Fragment>
{datas.map((data, index) => {
<li key={data.name}>
<input
type="text"
name="name"
value={data.name}
onChange={updateFieldChanged("name", index)}
/>
</li>;
<li key={data.gender}>
<input
type="text"
name="gender"
value={data.gender}
onChange={updateFieldChanged("gender", index)}
/>
</li>;
})}
</React.Fragment>
);
You can do this without mutation by mapping your old array into a new one, swapping what you want to change for an updated item along the way.
setDatas(
datas.map(item =>
item.id === index
? {...item, someProp : "changed"}
: item
))