Search code examples
javascriptreact-nativereduxstate

Making a change on a copy of a redux state also updates the actual state on redux store


I am seeing this behaviour where if i copy a redux state to a local variable and make a change to that variable it also updates my redux store without me using any kind of dispatching, here is my code:

// here is my action type inside my reducer 
case SET_USERS:
      return {
        ...state,
        users: action.payload,
      };

// and here i have a helper function to select a specific state and pass it to useSelector later on
export const getUsersSelector = (state: RootState) => {
  return state.app.users;
};

and i am accessing my state like this inside a custom hook useUsers i have

export const useUsers = () => {
   const users = useSelector(getUsersSelector);
   return {users}
}

and i am accessing my users value in another component using the useUsers hook:

const ListUsers = () => {
    const {users} = useUsers()
    //i make a copy of my users state
    const copyOfUsers = users
    
    //and update the copied variable
    copyOfUsers.push({name: 'John'})

    retunr (<View>{copyOfUsers.map((user)=><Text>{user.name}</Text>)}</View>)
}

the issue i am having is pushing a new item to my copyOfUsers variable also updates the users state inside the redux store, i dont know why this is happening and if its a normal behaviour, just wanted to know if this is a bug or intentional behaviour of redux? or how i can avoid it?


Solution

  • You are actually altering shallow copy of the users instance.

    You should first create a deep copy of the users instance and then operate on the data.

    The users is an Array so, you could have used slice to create a deep copy and then should have pushed the new object in the new copy of the users. That would have prevented the reflection of mutation in your redux copy.

    Your code should look like:

     const {users} = useUsers()
     const copyOfUsers = users.slice() // this is actually created a deep copy of your array.
    
    copyOfUsers.push({name: 'John'}) // changing the new memory data 
    hence will not reflect in redux state.