Home > Mobile >  Updating state with nested array of objects without mutation
Updating state with nested array of objects without mutation

Time:03-25

I am trying to update my state. I want to be able to update a specific isChecked property when it is updated when a user clicks a checkbox. My state below:

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
        },
      ]
    }
  ]
}

This is what I have tried. I have to map twice to get to the roles and then set the conditions, however, I am assuming I am mutating the state with another new one so when I render it, it breaks.

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))
      }))
  }

Is there a cleaner way to do this without mutation? Thanks.

CodePudding user response:

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,
   };
});

I have changed your state structure,I think it is more readable and you can read the state object and debug it much better

CodePudding user response:

your object changes to this after you run it through your maps enter image description here

this.setState((state) => {
  const { userPermissions } = state;
  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)
    ]
  };
});
  • Related