Update state where value = x in Redux/React

97 views Asked by At

I have an array of users in my store set up like this:

{users: {user_id: 1, user_name: Adam, user_score: 100}, 
{user_id: 2, user_name: Bob, user_score: 200}, 
{user_id: 3, user_name: Charlie, user_score: 300}}

My project is receiving JSON data from the server that is set up like this:

{user_id: 1, score: 10}

I want to find where the user_id of the passed data matches the existing user set's user_id and update the score to the score that was passed in.

For example, if the reducer receives {user_id:2, score:10} how do I change the score to 10 where the user id equals 2 in the original state. While avoiding mutation, of course!

What would be the best way to use do this? Normalizr? Lodash? update()? Seems pretty simple, I must be missing something obvious here. Thanks.

2

There are 2 answers

0
Harkirat Saluja On

I would suggest using immutable.js for this purpose.

Pass the id of the user which you want to update to the action and from there pass it to the reducer and use immutable to update the user data.

So you code in immutable would be something like

  const data = Immutable.fromJS(state)
  const newState = data.setIn(['users', user_id, 'score'], 10);
  return newState.toJS()

P.S: I havent tested the above but it should work(if not modify a little)

You can read about immutable here.

Also I would suggest going through a similar answer here

0
Paul S On

In your reducer, you can iterate through the existing users array and set a new value for the one that matches the user_id.

function usersReducer(state = [], action) {
  switch (action.type) {
  case 'UPDATE_SCORE':
    var { user_id, score } = action
    return state.map(u => {
      if (u.user_id === user_id) {
        // for the matching user, return an
        // object with the updated score
        return Object.assign({}, u, { score })
      } else {
        // for all other users, return the
        // existing object
        return u
      }
    })
  default:
    return state
  }
}