28
Redux: Never Mutate State
- Today FreeCodeCamp will be giving us a lesson about enforcing the key [principle of state immutability in Redux. Which means that you never modify state directly. Instead you return a new copy of state.
- Redux does not actively enforce state immutability in its store or reducers. Remember strings and numbers are primitive values and are immutable by nature. In other words, 3 is always 3. You cannot change the value of the number 3. An array or object, however, is mutable.
- Code:
const ADD_TO_DO = 'ADD_TO_DO';
// A list of strings representing tasks to do:
const todos = [
'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code',
];
const immutableReducer = (state = todos, action) => {
switch(action.type) {
case ADD_TO_DO:
// Don't mutate state here or the tests will fail
return
default:
return state;
}
};
const addToDo = (todo) => {
return {
type: ADD_TO_DO,
todo
}
}
const store = Redux.createStore(immutableReducer);
Above we have a
store
andreducer
in the code editor for managing to-do items. You have to finish writing theADD_TO_DO
case in the reducer to append a new-to-do to the state. You have tp find a way to return a new array with the item from action.todo appended to the end.Answer:
const ADD_TO_DO = 'ADD_TO_DO';
const todos = [
'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code',
];
const immutableReducer = (state = todos, action) => {
switch(action.type) {
case ADD_TO_DO:
let newList = [...todos]
newList.push(action.todo)
return newList;
default:
return state;
}
};
const addToDo = (todo) => {
return {
type: ADD_TO_DO,
todo
}
}
const store = Redux.createStore(immutableReducer);
store.dispatch(addToDo('PS5 Time'))****
console.log(store.getState()) //
[ 'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code',
'PS5 Time' ]
console.log(todos) //
[ 'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code' ]
- (ES6) To help enforce state immutability in Redux is the spread operator:
....
which I used in the lesson above which produces a new array from an existing array. - To clone an array but add additional values in the new array, you could write
[...myArray, 'new value']
. This would return a new array composed of the values in myArray and the string new value as the last value. It's important to know that it only makes a shallow copy of the array. It only provides immutable array operations for one-dimensional arrays.
Code:
const immutableReducer = (state = ['Do not mutate state!'], action) => {
switch(action.type) {
case 'ADD_TO_DO':
// Don't mutate state here or the tests will fail
return
default:
return state;
}
};
const addToDo = (todo) => {
return {
type: 'ADD_TO_DO',
todo
}
}
const store = Redux.createStore(immutableReducer);
- Answer:
const immutableReducer = (state = ['Do not mutate state!'], action) => {
switch(action.type) {
case 'ADD_TO_DO':
let newArray = [...state, action.todo]
return newArray
default:
return state;
}
};
Now we gotta practice removing items from an array. Other useful JavaScript methods include
slice()
andconcat()
.The reducer and action creator were modified to remove an item from an array based on the index of the item. Let's Finish writing the reducer so a new state array is returned with the item at the specific index removed.
*Code:
const immutableReducer = (state = [0,1,2,3,4,5], action) => {
switch(action.type) {
case 'REMOVE_ITEM':
// Don't mutate state here or the tests will fail
return
default:
return state;
}
};
const removeItem = (index) => {
return {
type: 'REMOVE_ITEM',
index
}
}
const store = Redux.createStore(immutableReducer);
- Answer:
const immutableReducer = (state = [0,1,2,3,4,5], action) => {
switch(action.type) {
case 'REMOVE_ITEM':
let a = state.slice(0, action.index)
let b = state.slice(action.index + 1)
return a.concat(b)
default:
return state;
}
};
const removeItem = (index) => {
return {
type: 'REMOVE_ITEM',
index
}
}
const store = Redux.createStore(immutableReducer);
Larson, Q., 2019. Frontend Development Libraries. [online] Freecodecamp.org. Available at: https://www.freecodecamp.org/learn/front-end-development-libraries/redux
28