我的React组件中有此状态->
const [employeeState, setEmployee] = useState({
"empName": null,
"Age": null,
"depts": [], //depts is an array of objects
"groups": [] //group is an array of objects
});
我对部门和小组有单独的状态,如下所示->
const depts = {
"name": "some name",
"code": "s123",
}
const [deptState, setDeptState] = useState([
{ ...depts},
]);
团体也一样。...
现在,当我尝试在某些btn点击上设置员工状态时,如下所示,它没有更新并保持depts
和groups
属性为空->
const deptsLst = [...deptState];
const groupsLst = [...groupstate];
console.log(depsLst); // this will print the results as expected
console.log(groupsLst); // this will print the results as expected
setEmployee({
...employeeState,
['depts']: deptsLst ,
['groups']: groupsLst ,
})
console.log(employeeState);// this will show depts and groups as empty only
我对这种传播变量复制概念并不陌生。我在这里做什么错了?
答案 0 :(得分:1)
您可以这样做:
setEmployee({
...employeeState,
depts: deptsLst,
groups: groupsLst
})
更新您的employeeState。之后,您可能不会看到带有console.log
的更新,因为它将在状态更新之前执行。您可以使用以下employeeState
函数来验证useEffect
是否已更新:
useEffect(() => {
console.log(employeeState)
}, [employeeState])
spread运算符是ES6复制阵列的一种方式,无需传递对副本的引用,因此您可以修改一个阵列而不会在其他阵列中显示这些更改。您可以在这里进一步了解:Reference And Copying Objects & Arrays。
答案 1 :(得分:1)
您声明“我不是这个传播变量复制概念的新手” ...不仅是传播操作的新手,而且您的代码表明您对它没有基本的了解。您无缘无故地在计算机属性名称的顶部使用了扩展运算符。
您还使用React状态来管理雇员对象,然后使用React状态来管理雇员对象上的Array属性。如果您已经在对employee对象执行状态管理,为什么要维护单个属性的状态?
确定代码的几个细目:
const depts = {
"name": "some name",
"code": "s123",
}
const [deptState, setDeptState] = useState([
{ ...depts},
]);
上面您无缘无故地克隆对象。
使用React状态管理,您只需克隆对象即可触发渲染事件。克隆将在内存中创建一个具有新引用的新对象,将“响应”对象引用更改并触发状态更改事件。 React无法监视复杂对象的每个属性,尤其是数组元素,以查看值是否已更改。
下面的代码就足够了,您正在初始化状态,无需克隆:
const [deptState, setDeptState] = useState([{
"name": "some name",
"code": "s123",
}]);
接下来的代码:
setEmployee({
...employeeState,
['depts']: deptsLst ,
['groups']: groupsLst ,
})
在这里,您尝试使用传播运算符来克隆“ employeeState”对象,并更新depts
属性键和groups
属性键的新值。您无缘无故地将“计算出的属性名称”用作属性键。
这就足够了:
setEmployee({
...employeeState,
depts: deptsLst ,
groups: groupsLst
})
您还会创建不必要的状态:
const [deptState, setDeptState] = //..rest of code omitted
在这里您没有意识到React状态更改是异步发生的:
setEmployee({
...employeeState,
['depts']: deptsLst ,
['groups']: groupsLst ,
})
console.log(employeeState);
上面的代码实际上已经更改了employeeState,只是不是您的console.log(employeeState)
的时间;
好的,首先,我有created a CodePen供您了解状态如何变化。
当您要更改此雇员对象的状态时,只需更改对象属性值或添加新属性值,然后克隆雇员对象以更改其引用,然后使用克隆调用setState,请考虑使用此对象状态:
const [employee, setEmployee] = React.useState({
"empName": 'Jane Doe',
"Age": 33,
"depts": [
{
"name": "some name",
"code": "s123",
}
]
});
这里我要向员工添加部门,请注意,我仅克隆员工对象以触发React来检测总体对象引用更改,React不知道我更改了属性depts
数组,但是新状态确实具有我在部门数组上施加的新值:
function exampleUpdatingEmployee() {
employee.depts.push({
"name": "some new dept",
"code": "876",
});
setEmployee({ ...employee });
}
答案 2 :(得分:0)
如果depts和group是对象数组,则应使用散布运算符以这种方式复制值:
setEmployee({
...employeeState,
depts: [...deptState],
groups: [...groupstate]
});
所以如果:
const employeeState = {status: 'hungry'};
const deptState = ['one', 'two'];
const groupstate = ['y', 'k', 'o'];
然后,散布后的第一个代码如下:
setEmployee({
status: 'hungry',
depts: ['one', 'two'],
groups: ['y', 'k', 'o']
});