In this Writer’s Room blog, Andela Community Member Ebenezer Adjei explores the new and improved Redux – Redux Toolkit – and its capabilities for the future of State Management!
Redux Toolkit is a great tool that has finally taken over the core Redux. It encompasses all the features of Redux with extra capabilities. When using the Redux toolkit, you’re using Redux that has been made more efficient. This article gives an overview of using Redux in your applications and why you should not use the core redux package. However, if you are already familiar with how redux works, skip to “Use Redux toolkit instead of the core Redux.”
The advent of single-page applications has popularized terms such as “state management.”
One important aspect of modern Single Page Applications(SPAs) is managing data within the application and making data available at different parts of the application. There is no one-stop approach to doing this. However, there are best practices to consider when building applications for production. In managing data, one needs to ensure that the data flowing through the application is consistent, accurate, and has a single source of truth. Generally, as your application grows bigger, the effort needed to manage state and consistent data also increases. This makes it quite difficult when choosing the best approach for state management.
Over the years, many libraries have been developed to fulfill this purpose. One very popular library among these is “Redux”. Redux is so popular that sometimes people see it as a necessity for building react applications. On the contrary, Redux is not a MUST for building react applications. It only becomes necessary when your application needs it. You can build a fully fledged, very performant react application without Redux. This however, does not undermine the power of redux. When used in an application, Redux is able to manage state and data flow within the application very efficiently.
How redux works
Redux is a pattern and library for managing and updating application state, using events called “actions”. It serves as a centralized store for state that needs to be used across your entire application, with rules ensuring that the state can only be updated in a predictable fashion. (official docs).
A typical Redux setup consists of:
- Actions: A Redux action has a type and a payload. The type defines the type of action that is sent to the reducer and the payload is the data that the reducers uses to update the store. Redux actions are functions which are sent from the UI components. When an action is triggered inside a component, it is sent to the reducer through a dispatcher.
- Reducers: Reducers are the only means by which one can update the Redux store. The reducer receives an action and manipulates the state based on the action type and the payload.
- State: The state is the place where the data lives. When components are connected to the state, an update to the state causes those components to re-render.
How your application uses redux
When Redux is used in an application, all components are able to access the store directly without passing through other components. From the diagram above, we can see that there is a common store where all the components can access data from. All components can get data from the store without passing through any other component. When a component dispatches an action to the reducer, the store gets updated and all other connected components get notified to receive the update. This makes it easy for parent components to send state updates to child components. Without Redux, any update from the parent has to pass through all connected components before reaching the child component. Doing this manually is cumbersome and introduces another problem called prop dilling. Prop drilling is a situation where data is passed down through several components before reaching the component that needs the data.
A few things to consider before using redux
If you are in doubt whether to use Redux or not, consider these typical instances where you will want to use Redux in your application:
- You have large amounts of application state that are needed in many places in the app
- The app state is updated frequently
- The logic to update that state may be complex
- The app has a medium or large-sized codebase, and might be worked on by many people
- You need to see how that state is being updated over time
- Don’t use the core Redux, use Redux tool kit
Source: Redux docs
Use Redux toolkit instead of the core Redux
Over the years, Redux has undergone several upgrades and quite recently, Redux toolkit was released; which is a massive improvement over the previous versions. If you have used the early versions of Redux, you will definitely love using the new redux toolkit. In fact Redux toolkit is a game changer.
If you decide to use Redux in your application, don’t use the core Redux. Instead go for the Redux toolkit. I have had a great experience using the Redux toolkit which makes me always happy to talk about it. In the early days of Redux, many developers complained about a common problem; it was difficult to setup and required a lot of boilerplate code. As a personal experience, I always found it tedious and repetitive defining action constants and passing them to action creators. When I check my old Redux code, I see tons of switch statements which match actions based on the action constants. One was expected to write action constants and switch statements for as many actions that they would define. This wasn’t only verbose but quite repetitive. Thanks to Redux toolkit, this is now a thing of the past.
The advent of Redux toolkit has brought very great improvement to the redux ecosystem. It is an improvement of the old Redux. Ever since I used the new Redux toolkit, I hate to write code using the old Redux. In fact, the new Redux toolkit is marvelous. You could increase productivity over 50% with the Redux toolkit over the old Redux.
Advantages of Redux toolkit over the old redux
- It removes redundant boilerplate code
- It is easy to set up (you do not have to write a lot of code and install packages)
- It increases productivity (time spent writing action constants could be used for something else)
- It allows you to write immutable code in a mutating manner. The redux toolkit uses the immer library under the hood which tracks changes to your state. Even though you can update your state in a mutating manner, the immer library keeps track of the changes and updates your store immutably.
Use Redux hooks instead of the connect api
Redux toolkit introduces several hooks which makes it easier to select data from the store. Previously, most developers relied on mapStateToProps and mapDispatchToProps to fetch data from the store and to send actions to the reducer respectively. Components needed to be wrapped around a higher order component called “connect” wrapper. Even though mapStateToProps and mapDispatchToProps still work fine with the new Redux toolkit, it’s more efficient to use the hooks that come with Redux toolkit. Check below for a few reasons why you should use redux hooks.
- Redux hooks are the future
- Redux hooks are more aligned with the future of React
- Redux hooks are more concise and easy to understand
- Redux hooks are easier to use with Typescript
- Use selectors to select small portions of your state
- Use “useSelector” instead of mapStateToProps to make selecting state easier
- Use “useDispatch” instead of “mapDispatchToProps” to make dispatching actions easier
Steps to add Redux toolkit to your project.
Redux toolkit is easy to setup and you can get started without any hassle.
1. Install packages from the official docs
2. Create a Redux Slice
The slice is made up of actions and reducers and it represents a small portion of the state that is saved in the redux store. It is good practice to keep different parts of the state in smaller slices and to avoid using nested objects within the slices. To create a slice, you have to provide a string name, an initial state and at least one reducer function to define how the state can be updated. The actions and the reducer functions can then be exported from the slice. Note that in this case we do not need to define action constants, action creators and reducers separately. They are all contained in the slice.
E.g. please check the snippet below
Note in the snippet above how we use a selector called “selectCount” to select value from the state. Alternatively, you can define a selector at the place where it is used instead of defining it in the slice. For example, ‘useSelector((state) => state.counter.value)’. Selectors help you to select just the portion of the state you need without passing everything in the state to your components.
- Configure Redux store
The store holds all the data that is sent to redux and it makes use of the reducers that are created in the slices. The store is passed to the root app component through a provider. By wrapping the store around the root app component, the app is able to receive any change that takes place in the store. When components are connected to the store through selectors or mapStateToProps, redux automatically passes all changes to the components which cause them to re-render.
When using redux toolkit, the reducers can be passed as an object to the store without calling a combine reducer function. This is possible because redux toolkit uses a function to combine the reducers under the hood.
4. Wrap your store around the root app component
5. Use redux in your components
Redux toolkit simplifies development with Redux and makes it more efficient. Please check the official documentation for more resources.
When it comes to state management in React, there are many options available for different use cases. Before deciding on any of the options, you should understand the requirements of your application and decide on what is best for your use case.
You should however note that Redux is powerful and efficient but NOT a MUST for React applications.