Why You Should Use Redux Toolkit Library?

Kelechi Nwosu
The Andela Way
Published in
5 min readJan 9, 2020

When working on a Frontend project that has to make use of a state container, the go-to library for most engineers is Redux. This is a very good library for managing your states. Today I want to introduce you to another library from the redux team that will make the use of redux in your project effortless.

The library is called Redux Toolkit and is described as SOPE which stands for Simple, Opinionated, Powerful and Effective. You might be having questions like why is it called all this? what differentiates it from the standard redux library? how can it make my development easier?. Well, by the end of reading this article you would have answers to these questions and will be left to you to decide if using this library is suitable for you. so lets jump right in!

While working with the standard redux library, there are many issues we encounter which include

  • Redux requires additional installation of other libraries to make it more effective, an example is the reselect library, which is a selector library for redux.
  • Redux requires a lot of boilerplate code, which most developers don’t like doing, where you find yourself writing action creators over and over again for example.
  • Complicated configuration setup.

Redux Toolkit package was built in mind to so solve these cases by abstracting the setup process and also handling redux common use cases, to best illustrate this, I would be comparing a use case using the standard redux library with using the redux toolkit library.

Starting from action creators, let’s say we have a shopping cart we want to increment, the action creator function in a standard redux library will look like this

function incrementCart({itemId, value}) {
return {type: 'cart/increment', payload: {itemId, value}}
}
console.log(incrementCart({itemId: '2sdfdds', value: 1})) // prints {type: 'cart/increment', payload: {itemId: '2sdfdds', value: 1}}

Redux-toolkit provides a helper function called createAction which helps to simplify creating actions, here is how to create the incrementCart action function using redux-toolkit

const incrementCart = createAction('cart/increment')
console.log(incrementCart({itemId: '2sdfdds', value: 1})) // prints {type: 'cart/increment', payload: {itemId: '2sdfdds', value: 1}

As you can see, with just a line of code, we have created our incrementCart action and also we can see that the payload as been added for us automatically when calling the function with an argument passed to it.

Now let's create the reducer for our shopping cart, so creating our reducer using the redux library, we have:

// assuming that addToCart action has been called and the item is already in the storeconst initialStore = { '2sdfdds': 1}function shoppingCartReducer(state = initialStore, {type, payload}) {
const { itemId, value } = payload;
switch (type) {
case 'cart/increment':
return {...state, [itemId]: state[itemId] + value}
// ... other cases
default:
return state
}
}

Using the redux-toolkit library to create the reducer will look like this:

const incrementCart = createAction('cart/increment');const shoppingCartReducer = createReducer(initialStore, {
[incrementCart.type]: (state, action) => {
const {itemId, value} = action.payload;
state[itemId] = state[itemId] + value
}
// ... other cases
})

You will notice the code using redux-toolkit was written to mutate the state directly, which is a violation of a redux rule of keeping reducer functions pure. so why do we write it this way? That is one of the benefits of using redux-toolkit, the createReducer function was created in a way to allow us to use the function in a way that allows us to mutate the state, or seems to mutate the state, but behind the scenes, it doesn’t. This solves the issue with the redux library were changing the state implementation seems to be complex, where some might leverage on the use of the spread syntax of ES6 or make use of an immutable library just to make sure we don't mutate the state, but with the createReducer helper function, we can change the state conveniently and still keep our state predictable.

Next, we look at configuring our store, configuring our store using redux library looks like this:

function configureStore(preloadedState) {const middlewares = [loggerMiddleware, thunkMiddleware]const middlewareEnhancer = applyMiddleware(...middlewares)const enhancers = [middlewareEnhancer]const composedEnhancers = composeWithDevTools(...enhancers)const store = createStore(rootReducer, preloadedState, composedEnhancers)return store}

While this might be convenient to some (mostly because they are already used to it 🤪), but we are doing so many things just to configure our store, for example, we would use combineReducer for our rootReducer to combine all our reducers, configure our middlewares and enhancers, etc. The lines of code and configuration could be longer depending on the complexity of the application, which leaves room for errors. redux-toolkit provides a simpler function for configuring your store using the configureStore helper function. See for yourself:

function configureAppStore(preloadedState) {const store = configureStore({reducer: {
shoppingCart: shoppingCartReducer
// ... other reducers
},
middleware: [loggerMiddleware, ...getDefaultMiddleware()],preloadedState,})return store}

As you can see, not much configuration is required, we pass our object of reducers to the reducer option, this would combine the reducers for us, we don't need to combine the reducers our self, also we just need to pass our middlewares as arrays to the middleware option, the getDefaultMiddleware() function is also a function from redux toolkit to help pass other middlewares that you would need by default.

Some may argue that so far all they can see is that redux-toolkit just provides s functions for simplicity and there are still lots of boilerplates involved. Well here comes the fun part, redux-toolkit provides my favorite helper function of them all called createSlice, this function allows you to define reducer functions, the initial state, and generates the corresponding action creators and types, all from calling just one function. let me demonstrate in code so you would understand better

Let's say we want to replicate all that we have written in the shopping cart examples using createSlice, we will have:

const shoppingCartSlice = createSlice({   initialState,   name: 'cart',   reducers: {      increment: (state, action) => {         const {itemId, value} = action.payload;         state[itemId] = state[itemId] + value      }      // ... other reducers   }})const { increment } = shoppingCartSlice.actionsconst shoppingCartReducer = shoppingCart.reducerconsole.log(increment({itemId: '2sdfdds', value: 1})) // returns {type: 'cart/increment' payload: {itemId: '2sdfdds', value: 1}}

As you can see, with just a few lines of code, we have our action creators, reducers, action types created, and can all be in the same file. How cool is that 😎😃?!

I highly recommend that you make use of this library as it simplifies things and will save you a lot of development time, just as create-react-app does. This article doesn’t cover everything redux toolkit as to offer, so you can reference the documentation here to also gain more knowledge on this lifesaver of a library.

Happy Hacking!!!

--

--

Kelechi Nwosu
The Andela Way

Software Engineer — Building and Leading — Technology enthusiast. twitter: @kelechsky