Javascript 如何在React钩子中的对象数组中更新状态onchange
我检索了使用useState存储在对象数组中的数据,然后将数据输出到表单字段中。现在我希望能够在键入时更新字段(状态) 我似乎有人更新数组中属性的状态的例子,但从来没有更新过对象数组中的状态,所以我不知道怎么做。我已经将对象的索引传递给回调函数,但我不知道如何使用它更新状态Javascript 如何在React钩子中的对象数组中更新状态onchange,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我检索了使用useState存储在对象数组中的数据,然后将数据输出到表单字段中。现在我希望能够在键入时更新字段(状态) 我似乎有人更新数组中属性的状态的例子,但从来没有更新过对象数组中的状态,所以我不知道怎么做。我已经将对象的索引传递给回调函数,但我不知道如何使用它更新状态 // sample datas structure const datas = [ { id: 1, name: 'john', gender: 'm' }
// sample datas 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>
)
//样本数据结构
常数数据=[
{
id:1,
姓名:'约翰',
性别:'m'
}
{
id:2,
姓名:'玛丽',
性别:“f”
}
]
const[datas,setDatas]=useState([]);
常量updateFieldChanged=索引=>e=>{
console.log('索引:'+索引);
log('property name:'+e.target.name);
setData()/??
}
返回(
{datas.map((数据,索引)=>{
})
}
)
以下是您的操作方法:
//示例数据结构
/*常数数据=[
{
id:1,
姓名:'约翰',
性别:'m'
}
{
id:2,
姓名:'玛丽',
性别:“f”
}
]*///确保在useState调用中设置默认值(我已经修复了它)
const[datas,setDatas]=useState([
{
id:1,
姓名:'约翰',
性别:'m'
}
{
id:2,
姓名:'玛丽',
性别:“f”
}
]);
常量updateFieldChanged=索引=>e=>{
console.log('索引:'+索引);
log('property name:'+e.target.name);
让newArr=[…datas];//复制旧数据数组
newArr[index]=e.target.value;//将e.target.value替换为您想要更改的内容
setDatas(newArr);/??
}
返回(
{datas.map((数据,索引)=>{
})
}
)
您可以通过将旧数组映射到新数组,并将您要更改的内容替换为一个更新的项目来实现这一点,而无需改变
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>
);
const[datas,setDatas]=useState([
{
id:1,
姓名:“约翰”,
性别:“m”,
},
{
id:2,
姓名:“玛丽”,
性别:“f”,
},
]);
const updateFieldChanged=(名称、索引)=>(事件)=>{
让newArr=datas.map((项目,i)=>{
如果(索引==i){
返回{…项,[名称]:event.target.value};
}否则{
退货项目;
}
});
setDatas(newArr);
};
返回(
{datas.map((数据,索引)=>{
;
;
})}
);
您甚至不需要使用索引(如果需要,键除外)也不需要复制旧的数据数组,如果您希望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>
);
};
const初始数据=[
{
id:1,
姓名:“约翰”,
性别:“m”,
},
{
id:2,
姓名:“玛丽”,
性别:“f”,
},
];
const[datas,setDatas]=useState(初始数据);
返回(
{datas.map((数据,索引)=>(
{
data.name=e.target.value;
setDatas([…datas]);
}}
/>
))}
);
};
以@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是新值感谢它的作用。我可以针对对象中的任何特定属性名称,如
let propertyName=e.target.name代码>newArr[index][propertyName]=e.target.value代码>。但是在输入一个字母后,它没有聚焦在文本字段上,我必须再次单击该字段才能输入另一个字母。这很奇怪。我在JSFIDLE上做了一个修改,对我来说效果很好:好吧,我发现是
标记中的键导致了它,因为它与输入字段共享相同的值,所以当该值更改时,整个也会刷新。设置key={index}
修复了它。这会改变当前状态。Spread运算符只做浅拷贝。@vinayr在这种情况下,不需要深度拷贝。我的索引
指的是数组中对象的索引,而不是对象的属性id
,就像它要去的地方,但它确实需要一些解释。对我来说,这不太管用。我必须使用:setUsers(users.map(usr=>usr.subjectId===updateuser.subjectId?{……updateuser}:usr))
在我的例子中,subject是我列表中唯一的键。本质上,我映射列表并返回列表中的原始对象,除非id与我要更新的id匹配。在这种情况下,我将返回一个新对象,其中包含我更新对象的所有属性。上帝保佑。。。。。。