If you are a React Developer you have either used or heard of Redux. Redux became the most widely adopted state management tool for React, but has faced criticism along the way and has lost some popularity over the years. In complex, large applications you will likely have lots of components that use different pieces of state. Drilling your pops down levels and levels of your component tree gets messy fast. In comes Redux, a library used to extract your state from your components into a central store, which can be accessed anywhere in your application.
One of larger complaints of Redux, one that I have heard often, is “too much boilerplate code”. Redux takes a lot of hand written code to set up and effectively use it, which can push away a lot fo people. Creator of Redux, Dan Abramov, was aware of these concerns, which is why he and the Redux team built Redux Toolkit. Toolkit was created to address three main concerns of Redux.
- “Configuring a Redux store is too complicated”
- “I have to add a lot of packages to get Redux to do anything useful”
- “Redux requires too much boilerplate code”
Redux Toolkit abstracts a lot of the Redux practices and simplifies the code for users. You can still implement the whole power of Redux, just faster and with less lines of code. Toolkit syntax is now recognized by Redux as the standard configuration for Redux whether you are just learning it or a Redux master.
Overview of what is included in Redux Toolkit:
createStoreto provide simplified configuration options and good defaults. It can automatically combine your slice reducers, adds whatever Redux middleware you supply, includes
redux-thunkby default, and enables use of the Redux DevTools Extension.
createReducer(): that lets you supply a lookup table of action types to case reducer functions, rather than writing switch statements. In addition, it automatically uses the
immerlibrary to let you write simpler immutable updates with normal mutative code, like
state.todos.completed = true.
createAction(): generates an action creator function for the given action type string. The function itself has
toString()defined, so that it can be used in place of the type constant.
createSlice(): accepts an object of reducer functions, a slice name, and an initial state value, and automatically generates a slice reducer with corresponding action creators and action types.
createAsyncThunk: accepts an action type string and a function that returns a promise, and generates a thunk that dispatches
pending/fulfilled/rejectedaction types based on that promise
createEntityAdapter: generates a set of reusable reducers and selectors to manage normalized data in the store
createSelectorutility from the Reselect library, re-exported for ease of use.
(List from Redux.js.org)
Let’s take a look at an example of how configureStore API extracts logic and simplifies the store creation process in comparison to classic Redux.
This is quite a bit of logic to set up the store, let’s look at what is going on.
- Using combineReducers to combine the slice reducers to create the root reducer
- Import the root reducer into the store folder
- Bring in API’s: thunkMiddleware, applyMiddleware, and composeWithDevTools
- Creating the store with the root reducer
- Declare store enhancer with the dev tools and the middleware
- Finally, create the store using the root reducer.
That’s a lot of code just to whip up a store, but not to fear, Redux Toolkit is here. The API, configureStore is a wrapper around the createStore API that simplifies this process way down, let’s see.
Those two files of work was all extracted by the configureStore API.
Let’s break down what it did :
- Combined our reducers with the root reducer function that handles our state and created the store with that reducer.
- Added thunkMiddlware and Redux DevTools Extension.
Redux Toolkit streamlines the way we write our Redux code and it is so smooth! In the next post I will cover more of the features