![](/img/trans.png)
[英]Updating State of type Array<Object> in ReactJS without mutation
[英]Updating state with nested array of objects without mutation
我正在尝试更新我的 state。我希望能够在用户单击复选框时更新特定的 isChecked 属性。 我的state如下:
this.state = {
userPermissions: [
{
appName: "Dashboard",
roles: [
{
appId: "1",
statusId: 1,
isChecked: false
},
{
appId: "1",
statusId: 2,
isChecked: true
},
]
},
{
appName: "Finance",
roles: [
{
appId: "2",
statusId: 3,
isChecked: false
},
{
appId: "2",
statusId: 4,
isChecked: true
},
]
}
]
}
这是我试过的。 我必须 map 两次才能找到角色,然后设置条件,但是,我假设我正在用另一个新的 state 进行变异,所以当我渲染它时,它会中断。
handleCheck = (e, data) => {
const checked = e.target.checked;
this.setState(prevState => ({
userPermissions: prevState.userPermissions
.map(item => item.roles
.map(item => item.appId === data.appId && item.statusId === data.statusId ? { ...item, isChecked: checked } : item))
}))
}
有没有更干净的方法来做到这一点而不突变? 谢谢。
this.setState((state) => {
const { userPermissions } = state;
const index = userPermissions.findIndex(e => e.roles.findIndex(ee => ee.appId === "1")!= -1)
const roleIndex = userPermissions[index].roles.findIndex(role => role.appId === "1")
return {
...state,
userPermissions: [
...userPermissions.slice(0, index),
Object.assign(
{ ...userPermissions.slice[index] },
{
roles: [
...userPermissions[index].roles.slice(0, roleIndex),
Object.assign(userPermissions[index].roles[roleIndex], {
isChecked: !userPermissions[index].roles[roleIndex].isChecked
}),
...userPermissions[index].roles.slice(roleIndex + 1)
]
}
),
...userPermissions.slice(index + 1)
]
};
});
let state = {
keys: ['Finance', 'Dashboard'],
Finance: [
{
appId: '2',
statusId: 3,
isChecked: false,
},
{
appId: '2',
statusId: 4,
isChecked: true,
},
],
Dashboard: [
{
appId: '1',
statusId: 1,
isChecked: false,
},
{
appId: '1',
statusId: 2,
isChecked: true,
},
],
};
this.setState(prev => {
let Finance = prev.Finance.map(item =>
item.appId === data.appId && item.statusId === data.statusId
? { ...item, isChecked: checked }
: item
);
let Dashboard = prev.Dashboard.map(item =>
item.appId === data.appId && item.statusId === data.statusId
? { ...item, isChecked: checked }
: item
);
return {
keys: prev.keys,
Finance,
Dashboard,
};
});
我已经更改了你的 state 结构,我认为它更具可读性,你可以阅读 state object 并更好地调试它
如果将来有人对此有任何疑问,我已经发布了解决此问题的方法。 我觉得这是一个更清洁的解决方案。
const { userPermissions } = this.state;
const { checked } = e.target;
//find the app index
const appIndex = userPermissions.findIndex(element => element.appName === data.appName);
//find the status index
const roleIndex = userPermissions[appIndex].roles.findIndex(role => role.statusId=== data.statusId);
//create a copy of state
let newArr = [...userPermissions];
//make change on isChecked
newArr[appIndex].roles[roleIndex] = { ...newArr[appIndex].roles[roleIndex], isChecked: checked };
this.setState({
userPermissions: newArr
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.