如何在 React Hooks 的对象数组中更新状态 `onChange`
How do I update states `onChange` in an array of object in React Hooks
我检索了使用 useState
存储在对象数组中的数据,然后将数据输出到表单字段中。现在我希望能够在输入时更新字段(状态)。
我看到有人更新数组中 属性 的状态的示例,但从来没有更新对象数组中的状态,所以我不知道该怎么做。我已将对象的索引传递给回调函数,但我不知道如何使用它更新状态。
// sample data structure
const datas = [
{
id: 1,
name: 'john',
gender: 'm'
}
{
id: 2,
name: 'mary',
gender: 'f'
}
]
const [datas, setDatas] = useState([]);
const updateFieldChanged = index => e => {
console.log('index: ' + index);
console.log('property name: '+ e.target.name);
setData() // ??
}
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>
)
操作方法如下:
// sample data structure
/* const data = [
{
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 [data, setData] = 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 = [...data]; // copying the old datas array
newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to
setData(newArr);
}
return (
<React.Fragment>
{data.map((datum, index) => {
<li key={datum.name}>
<input type="text" name="name" value={datum.name} onChange={updateFieldChanged(index)} />
</li>
})}
</React.Fragment>
)
您可以通过将旧数组映射到新数组,并在此过程中将您想要更改的内容换成更新的项目,从而在不进行突变的情况下执行此操作。
setDatas(
datas.map(item =>
item.id === index
? {...item, someProp : "changed"}
: item
))
我是这样做的:
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>
);
您甚至不需要使用索引(如果需要,可以使用键除外),也不需要复制旧数据数组,甚至可以内联或将数据作为参数传递,如果您更喜欢 updateFieldChanged不是内联的。这样很快就完成了:
const initial_data = [
{
id: 1,
name: "john",
gender: "m",
},
{
id: 2,
name: "mary",
gender: "f",
},
];
const [datas, setDatas] = useState(initial_data);
return (
<div>
{datas.map((data, index) => (
<li key={index}>
<input
type="text"
value={data.name}
onChange={(e) => {
data.name = e.target.value;
setDatas([...datas]);
}}
/>
</li>
))}
</div>
);
};
基于@Steffan,按照您的方式使用:
const [arr,arrSet] = useState(array_value);
...
let newArr = [...arr];
arr.map((data,index) => {
newArr[index].somename= new_value;
});
arrSet(newArr);
使用 useEffect 检查新的 arr 值。
setDatas(datas=>({
...datas,
[index]: e.target.value
}))
索引为目标位置,e.target.value新值
聚会有点晚了,但是可以选择将数组的内容散布在一个新对象中,然后替换所选索引中的所需对象,最后从该结果生成一个数组,它是简短的回答,可能不是大型阵列的最佳选择。
// data = [{name: 'tom', age: 15, etc...}, {name: 'jerry', age: 10, etc...}]
// index = 1
setData(Object.values({...data, [index]: {...data[index], name: 'the mouse' }}))
// data = [{name: 'tom', age: 15, etc...}, {name: 'the mouse', age: 10, etc...}]
在此之前展开阵列。因为你不能不使用 useState
返回的方法直接更新钩子
const newState = [...originalState]
newState[index] = newValue
setOriginalState(newState)
如果它是一个字符串数组,这将修改状态的值并更新 useState 挂钩。
const updateFieldChanged = index => e => {
name=e.target.name //key
let newArr = [...data]; // copying the old datas array
newArr[index][name] = e.target.value; //key and value
setData(newArr);
}
return (
<React.Fragment>
{data.map((datum, index) => {
<li key={datum.name}>
<input type="text" name="name" value={datum.name} onChange={updateFieldChanged(index)} />
</li>
})}
</React.Fragment>
)
我检索了使用 useState
存储在对象数组中的数据,然后将数据输出到表单字段中。现在我希望能够在输入时更新字段(状态)。
我看到有人更新数组中 属性 的状态的示例,但从来没有更新对象数组中的状态,所以我不知道该怎么做。我已将对象的索引传递给回调函数,但我不知道如何使用它更新状态。
// sample data structure
const datas = [
{
id: 1,
name: 'john',
gender: 'm'
}
{
id: 2,
name: 'mary',
gender: 'f'
}
]
const [datas, setDatas] = useState([]);
const updateFieldChanged = index => e => {
console.log('index: ' + index);
console.log('property name: '+ e.target.name);
setData() // ??
}
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>
)
操作方法如下:
// sample data structure
/* const data = [
{
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 [data, setData] = 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 = [...data]; // copying the old datas array
newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to
setData(newArr);
}
return (
<React.Fragment>
{data.map((datum, index) => {
<li key={datum.name}>
<input type="text" name="name" value={datum.name} onChange={updateFieldChanged(index)} />
</li>
})}
</React.Fragment>
)
您可以通过将旧数组映射到新数组,并在此过程中将您想要更改的内容换成更新的项目,从而在不进行突变的情况下执行此操作。
setDatas(
datas.map(item =>
item.id === index
? {...item, someProp : "changed"}
: item
))
我是这样做的:
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>
);
您甚至不需要使用索引(如果需要,可以使用键除外),也不需要复制旧数据数组,甚至可以内联或将数据作为参数传递,如果您更喜欢 updateFieldChanged不是内联的。这样很快就完成了:
const initial_data = [
{
id: 1,
name: "john",
gender: "m",
},
{
id: 2,
name: "mary",
gender: "f",
},
];
const [datas, setDatas] = useState(initial_data);
return (
<div>
{datas.map((data, index) => (
<li key={index}>
<input
type="text"
value={data.name}
onChange={(e) => {
data.name = e.target.value;
setDatas([...datas]);
}}
/>
</li>
))}
</div>
);
};
基于@Steffan,按照您的方式使用:
const [arr,arrSet] = useState(array_value);
...
let newArr = [...arr];
arr.map((data,index) => {
newArr[index].somename= new_value;
});
arrSet(newArr);
使用 useEffect 检查新的 arr 值。
setDatas(datas=>({
...datas,
[index]: e.target.value
}))
索引为目标位置,e.target.value新值
聚会有点晚了,但是可以选择将数组的内容散布在一个新对象中,然后替换所选索引中的所需对象,最后从该结果生成一个数组,它是简短的回答,可能不是大型阵列的最佳选择。
// data = [{name: 'tom', age: 15, etc...}, {name: 'jerry', age: 10, etc...}]
// index = 1
setData(Object.values({...data, [index]: {...data[index], name: 'the mouse' }}))
// data = [{name: 'tom', age: 15, etc...}, {name: 'the mouse', age: 10, etc...}]
在此之前展开阵列。因为你不能不使用 useState
返回的方法直接更新钩子const newState = [...originalState]
newState[index] = newValue
setOriginalState(newState)
如果它是一个字符串数组,这将修改状态的值并更新 useState 挂钩。
const updateFieldChanged = index => e => {
name=e.target.name //key
let newArr = [...data]; // copying the old datas array
newArr[index][name] = e.target.value; //key and value
setData(newArr);
}
return (
<React.Fragment>
{data.map((datum, index) => {
<li key={datum.name}>
<input type="text" name="name" value={datum.name} onChange={updateFieldChanged(index)} />
</li>
})}
</React.Fragment>
)