简体   繁体   中英

Using concat rather than push in redux

I am working on setting up redux in my React project and wanted to confirm something regarding avoiding mutating state.

When one needs to add a new element to an array, my understanding is that one should use something like concat , rather than push , because even if one first uses the spread operator to copy an array, the new array will still point to the same location in memory as the original array. So when one then uses push on the new array, it's still mutating the original. Therefore, one should use concat , which, unlike push , won't touch the original array.

Therefore instead of this:

case 'CREATE_STORY':
  newState = [
    ...state,
  ]
  newState.push(action.payload);
  return newState;

One should do something like this:

case 'CREATE_STORY':
  newState = [
    ...state,
  ]
  newState.concat([action.payload]);
  return newState;

Is that correct?

because even if one first uses the spread operator to copy an array, the new array will still point to the same location in memory as the original array. So when one then uses push on the new array, it's still mutating the original.

It's incorrect, you won't mutate the original state, therefore this code is valid:

const newState = [...state];
newState.push(action.payload);
// newState !== state, will render as expected
return newState;

But usually, it's better not to use .push or any mutating functions at all ("code smell", may lead to bugs if not used carefully). That's because in React we should treat everything as immutable, see the power of not mutating data in docs.


The problem with .concat is that you never remember what this function does (it returns a shallow copy?). So basically you want to write a consistent code that you will understand immediately.

You want to add a new element to an array? Use spread syntax:

return [...state, action.payload]

You need to do it in one line

return newState.concat([action.payload]);

because concat only returns a concated array, and won't change your newState

Personal preference only, if your state is an array and you need to change it, I find it more succint to do things in one line instead of creating variables like newState


 case REMOVE_ITEM:
    return state.filter(item => item !== action.payload);

 case APPEND_ITEM:
    return [...state, action.payload]

 case CHANGE_ITEM:
    return state.map(item => item === action.payload.oldItem ? action.payload.newItem : item)

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