Eric P Pereira
Eric P Pereira

Reputation: 440

React / Redux: Correct way to update object in reducer

I'm having trouble updating an object in my React / Redux reducer. The initial state is an object of Immutable. I'm stuck trying to update the object.

import Immutable from 'immutable';
import * as actionTypes from '../actions/actionTypes';

const initialState = Immutable.fromJS({
  user: {
    id: null,
    name: null,
    age: null
  }
});

export default function addUserReducer(state = initialState, action) {
  switch(action.type) {
    case actionTypes.ADD_USER:
      const user = {
        id: action.id,
        name: action.name,
        age: action.age
      }

      return state.setIn(['user'], user);
    default:
      return state;
  }
}

The state always returns a map with the values of id, name and age as null.

What's the correct way to update the state in my reducer?

Upvotes: 1

Views: 3116

Answers (2)

Supermacy
Supermacy

Reputation: 1479

Use merge function in immutable to change the state.It can be implemented like this

import Immutable from 'immutable';
import * as actionTypes from '../actions/actionTypes';

const initialState = Immutable.fromJS({
  user: {
    id: null,
    name: null,
    age: null
  }
});

export default function addUserReducer(state = initialState, action) {
  switch(action.type) {
    case actionTypes.ADD_USER:
      // This will update the state in the reducer if you are using immutable library
      return state.merge({
        id: action.id,
        name: action.name,
        age: action.age
      });
    default:
      return state;
  }
}

Upvotes: 1

R V
R V

Reputation: 143

Your code looks ok, and when I run it in a repl it works.

I tested it by adding the following:

const newState = addUserReducer(undefined, {
  type: 'ADD_USER', // I just assumed that's what your type resolves to.
  id: 1,
  name: 'FOO',
  age: 100,
});
console.log(newState); // Logs "Map { "user": [object Object] }"
console.log(Immutable.Map.isMap(newState); // true
console.log(Immutable.Map.isMap(newState.get('user'))) //false

I suspect the reason it's not working for you is because your action's actual type does not actually equal actionTypes.ADD_USER. I would double check that case in the reducer runs. A simple log in that case should tell you.

Also, like other comments have said above, right now your ADD_USER case is setting the user as a NON-Immutable object, so instead modify the ADD_USER return statement like so:

state.set('user', Immutable.Map(user));

Also note that since 'user' is a top-level key, Maps .set method works just fine.

Upvotes: 0

Related Questions