Because Redux reducers must never mutate state, we often write immutable updates by using JavaScript’s array and object spread operators and other functions that return copies of the original values. However, accidentally mutating state in reducers is the single most common mistake Redux users make!

While you still have the option of writing immutable updates the old fashioned way, Redux Toolkit’s createSlice() function uses a library called Immer inside of it which helps avoid this mistake.

Immer uses a special JS object called a Proxy to wrap the data you provide and lets you write code that “mutates” that wrapped data. Immer does this by tracking all the changes you’ve made and then uses that list of changes to return an immutably updated value as if you’d written all the immutable update logic by hand.

So, instead of this:

const todosSlice = createSlice({ name: 'todos', initialState: [], reducers: { addTodo: (state, action) => { return [ ...state, { ...action.payload, completed: false } ] }, toggleTodo: (state, action) => { return state.map(todo => todo.id === action.payload.id ? { ...todo, completed: !todo.completed } : todo ) } } })

You can write code that looks like this:

const todosSlice = createSlice({ name: 'todos', initialState: [], reducers: { addTodo: (state, action) => { state.push({ ...action.payload, completed: false }) }, toggleTodo: (state, action) => { const todo = state.find(todo => todo.id === action.payload.id) if (todo) { todo.completed = !todo.completed } } } })

addTodo is calling state.push() here, which is normally bad because the array.push() function mutates the existing array. Similarly, toggleTodo is simply finding the matching todo object, and then mutating it by reassigning its value.

Thanks to Immer, however, this code will work just fine!

You don’t need to learn the Immer library. All you do need to know is that createSlice() takes advantage of it, allowing us to safely “mutate” our state. You may find it useful to look through some of the common update patterns used with Immer.



Inside of the options object, rewrite the logic for the addRecipe case reducer so that it uses .push() instead of the spread operator to add a new recipe.

Take this course for free

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?