简体   繁体   中英

How to mutate a array on state in a redux reducer?

State prior to change looks like this:

foreignBases: [
  {
    base: {
      id: "5b8125ec14bb4f35f8f01aa9",
      ...
    },
    baseuser: {
      userId: "tester1",
      ...
    }
  },
  { base: { ... }, baseuser: { ... } }
]

via dispatch the user changes a boolean in the baseuser key to true , the reducer is then supposed to update the state for this particular key value pair, but I can't seem to get it right with this:

for (let i = 0; i < state.foreignBases.length; i++) {
  if (action.baseUser.created === state.foreignBases[i].baseuser.created) {
    return Object.assign({}, state, {
      foreignBases: [
        ...state.foreignBases,
        {
          base: { ...state.foreignBases[i].base },
          baseuser: action.baseUser
        }
      ]
    });
}

This just adds another object to the state, when I really just need to replace one boolean of baseuser in one object

Be sure to check below for updates.

The spread operator is re-inserting the entire foreignBases, and then you're adding another object with what I assume is your intended mutation.

I'm thinking you mean something like this (untested)

for (let i = 0; i < state.foreignBases.length; i++) {
  if (action.baseUser.created === state.foreignBases[i].baseuser.created) {
    let foreignBases = [...state.foreignBases];
    foreignBases[i].baseuser = action.baseUser;
    return Object.assign({}, state, {foreignBases});
  }
}

Update : @devserkan reminded me that the spread operator "does not do a deep copy", which is a no-no in Redux! So I went looking for the updating an item in an array official pattern , which I believe is applied like this (again, untested):

let foreignBases = state.foreignBases.map((foreignBase) => {
  if (action.baseUser.created === foreignBase.baseuser.created) {
    return {action.baseUser};
  } else {
    return foreignBase
  }
});
return Object.assign({}, state,  { 
   ...foreignBase,
   baseuser: action.baseUser
});

Update 2 : @devserkan in the comments again contributes valuable insight, this time fixing the original for loop, by nesting in parts of the state object. Which is similar to mutation. This approach avoids that and allows you to still use a for loop.

for (let i = 0; i < state.foreignBases.length; i++) {
  if (action.baseUser.created === state.foreignBases[i].baseuser.created) {
    const newItem = {
      ...state.foreignBases[i],
      baseuser: action.baseUser
    };
    const newforeignBases = Object.assign([], state.foreignBases, {
      [i]: newItem
    });
    return Object.assign({}, state, { foreignBases: newforeignBases });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM