[React] Update state

Update nested state

Every level of nesting must by copied and updated appropriately

Mistake 1: New reference directly mutate original state

1
2
3
4
5
6
7
8
9
function updateNestedState(state, action) {
let nestedState = state.nestedState;
// this directly modifies the existing state
nestedState.nestedField = action.data;
return {
...,
nestedState
};
}

Mistake 2: Only making a shallow copy of one level

1
2
3
4
5
6
function updateNestedState(state, action) {
let newState = {...state}
// nestedState is still the same object
newState.nestedState.nestedField = action.data;
return newState;
}

Doing a shallow copy of the top level is not sufficient - the nestedState object should be copied as well.

Correct: Copy all level of nested data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function updateVeryNestedField(state, action) {
return {
...state,
first : {
...state.first,
second : {
...state.first.second,
[action.someId] : {
...state.first.second[action.someId],
fourth : action.someValue
}
}
}
}
}

Thus we should:

  • keep your state flattened
  • compose reducers as much as possible.

Updating array

As long as we make a copy first, we can safely mutate the copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function insertItem(array, action) {
let newArray = array.slice();
newArray.splice(action.index, 0, action.item);
return newArray;
}

function removeItem(array, action) {
let newArray = array.slice();
newArray.splice(action.index, 1);
return newArray;
}

// Or remove with filter
function removeItem(array, action) {
return array.filter( (item, index) => index !== action.index);
}

Updating an item in the array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function updateObjectInArray(array, action) {
return array.map( (item, index) => {
if(index !== action.index) {
// This isn't the item we care about - keep it as-is
return item;
}

// Otherwise, this is the one we want - return an updated value
return {
...item,
...action.item
};
});
}