Kevin Burton
Kevin Burton

Reputation: 2282

Object assign alone doesn't trigger a state change in React

I would like to know in the React/Redux world what is the difference between this

let newState = Object.assign({}, state);
newState[action.componentDescriptor.name][action.id].Value = action.value;
return newState;

and this

    return Object.assign({}, state, {
        [action.componentDescriptor.name]: objectAssign({}, state[action.componentDescriptor.name], {
            [action.id]: objectAssign({}, state[action.componentDescriptor.name][action.id], {
                Value: action.value
            })
        })
    });

It seems the former does not trigger a render (doesn't seem to be recognized as a state change). But the later is recognized as a state change and triggers a render. Both return new objects (state)?

Upvotes: 1

Views: 404

Answers (1)

devserkan
devserkan

Reputation: 17608

In the former one, you are using Object.assign once and this creates only a shallow copy. This means your object is copied just for one level and all the nested properties point the same references. So, when you directly change it Redux can't understand the difference.

In the later one (I presume you are doing it right) you are changing your state without mutating the original one and properly. You are creating copies of your nested properties with Object.assign. This is what makes the difference.

For a cleaner version, you can use spread syntax.

return {
  ...state,
  [action.componentDescriptor.name]: {
    ...state[action.componentDescriptor.name],
    [action.id]: {
      ...state[action.componentDescriptor.name][action.id],
      Value: action.value,
    }
  }
}

Or you can normalize your state to avoid so much nested mutations.

Upvotes: 1

Related Questions