Complex Reducers
Learn how to create, manage, and refactor complex reducers.
We'll cover the following...
Complex state management using Redux in a simple to-do app
To understand Redux in the context of a much larger state, let’s look at a more realistic example. The upcoming example describes a simple to-do app, and we’ll look at how to implement state management for this app. The to-do app will manage lists of to-do items and also contain a logged-in user area. The state will consist of two top-level properties:
todos
(oftype
array)user
(oftype
object)
This is reflected in our current state:
const initialState = Object.freeze({
user: {},
todos: [],
});
To ensure that a new state object is being created instead of mutating the previous object, the initial state object is wrapped by Object.freeze()
. If there is an attempt to mutate the **state object **directly, a TypeError
will be thrown:
'use strict';const initialState = Object.freeze({user: {},todos: [],});initialState.user = 'Lets change this state';
Let’s have a look at how a reducer function that manage the to-dos—meaning adding, removing, and changing the status of to-do items—and set the login area of a user:
const rootReducer = (state = initialState, action) => {switch (action.type) {case 'SET_USER': {return {user: {name: action.payload.name,accessToken: action.payload.accessToken,},todos: state.todos,};}case 'ADD_TODO': {return {user: state.user,todos: state.todos.concat({id: action.payload.id,text: action.payload.text,done: Boolean(action.payload.done),}),};}case 'REMOVE_TODO': {return {user: state.user,todos: state.todos.filter((todo) => todo.id !== action.payload),};}case 'CHANGE_TODO_STATUS': {return {user: state.user,todos: state.todos.map((todo) => {if (todo.id !== action.payload.id) {return todo;}return {...todo,done: action.payload.done,};}),};}default: {return state;}}};const store = createStore(rootReducer);
We won’t go into too much detail. However, a few things should be explained in depth. Let’s look at each switch
block, in which each ...