Meet us at:
- HackCrisis: Tech for Good Hackathon
- 17 - 22.03.2020 Online
- EUvsVirus Hackathon
- 24 - 26.04.2020 Online
- 27 - 28.08.2020 Tallinn, EE
- 17 - 18.09.2020 Copenhagen • Online
In this article, we share a short overview of state management and Flux architecture. Then we focus on the advantages and disadvantages of Redux and Context and, finally, recap and clarify when is best to use these tools.
On the other hand, with the newest version of React launches the new Context API. It seems these both tools could have the same responsibility in the application, but is it true?
In this article, we share a short overview of state management and Flux architecture. Then we focus on the advantages and disadvantages of Redux and Context and, finally, recap and clarify when is the best situation to use these tools.
Application state management is crucial in medium and large projects. It is useful in smaller and more manageable projects, but sometimes we can handle it without special libraries or patterns.
Usually, we explain state management for front-end applications as a sort of logic that keeps and refreshes current data. For example - is the radio button checked or not, is the user authenticated or not. More abstractly, it means to take care of complete business transactions - to maintain user interface inputs and possibly synchronize the data between pages, back-end, and front-end parts.
Additionally, it is an excellent subject to separate clean component rendering (or view) from the business layer.
For a more React point of view, proper state management keeps us from passing a lot of props from top-level elements to their destination grand-grandchildren. In some cases, we need a global state where all components could call for essential data. It doesn’t mean that everything should be universal. Some of the local variables are available only for one element and maybe their children, so it is good to keep them as they are (for example - is local field validation visible or not).
Before you read about Redux, let's make a brief overview of the Flux concept, which is popular in front-end applications, especially those prepared with React or Vue. Facebook recommends the flux architecture for creating SPAs (which is why many libraries support this data flow to React).
Flux based on the four parts of the application:
This part just manages the state. Here we have values from the UI and business layer. In the application should be only one "source of truth": stores (and we can have many stores). It is crucial to remember that a store manipulates the state (the state is only the data keeper). The store manages these data to handle business transactions.
So, how to change data? It is simple. Our store listens to all actions. Using implemented logic (for example, easy switch-case statements based on action names), the store chooses one of them to execute.
• Action (with Action Creators)
What is needed to execute an action should be inside a plain object. Commonly this is type field for action name (id) and payload for additional data.
Action Creators are little but impressive assistants to provide action. It is a good practice to encapsulate code. Instead of every time write the same lines for dispatch the same action, we can prepare a function that returns its type and maybe accepts payload.
This layer is a single object to share actions for all stores. The dispatcher broadcasts the called action.
• View (Presentation and Container)
View means a UI element. At this point, the component should render elements and handle user actions (like click button, type text, or drag & drop). In case of changes, the view is re-render.
All values are passed through props. These components should not call directly for them to the store. The same for actions - they can not have interactions with the dispatcher. Everything, even functions, comes from props.
These views are more powerful than the presentation parts. After user action containers dispatch actions, so they are connected to the dispatcher and the stores. Container Views task is to notice store changes and populate data for presentation elements.
Redux is still the most popular way for state management as a flux-based tool.
The first release of Redux was in June 2015, two years after React's initial launch. Dan Abramov and Andrew Clark are original authors of this solution.
Follow the rules to implement expected action for this library:
1. Only one central store. We cannot change its values, because this state is immutable.
2. Steps for updating the global state are inside reducer functions. The new state is returned as the result of its operations.
3. Use subscriptions for data to get refreshed values.
4. Actions are dispatched to call reducer functions.
• Common used (popularity) - a lot of problems are resolved by community
• Redux Toolkit - new impressive feature to limit boilerplate code
• Designed for often changed (refreshed) data
• Good React Redux package to integrate with React
• Better debug - there is a possibility to log state and actions
• Code organization - applications with Redux usually have similar architecture, so it is easier to understand the next one project for experienced developers
• Server-Side Rendering is available with Redux
• Not build-in in React (increases a final bundle size)
• May be misleading for beginners (a lot of hidden logic) even with Redux Toolkit
• More setup than Context API (and more terms to understand)
• Reuse components are harder because some data come from the global state, not from props
• Middleware for async tasks
A little curiosity about this tool: according to one section of its documentation, React Redux uses Context API inside to broadcast data for nested elements.
Since React v16.3.0 we can use not only new lifecycles methods. Context API comes with this version as well. Before this event React had experimental support for his feature, but now there is a more efficient, new context API.
What is Context? It is a smart built-in feature to solve problems with sharing data between nested (not directly connected) components.
• The build-in React tool has not influenced the final bundle size, and it is integrated by design with every npm package
• Easier to understand and handle for beginners than Redux data flow
• Excellent for more static data - not so frequency updated like in Redux
• Only little setup is required - create context and sometimes wrapper component
• Well documented part of React
• A lot of local contexts to handle separate logic tasks can be in the application.
• Not designed for often refreshed or changed data
• There could be more difficult maintenance in more complex applications, especially if we have custom solutions and helpers
• Reuse components are harder, because some data come from context, not always from props
When to use Redux?
Management of complex applications state seems to be an excellent task for Redux. It is a powerful tool to take care of all aspects of this part. Our app with this library applied could support server-side rendering, which sometimes is an essential feature—the same for debugging.
From the viewpoint of architecture, Redux helps us to keep project folders and files in order. This tool suggests split code into logical parts, as reducer or actions. It allows developers to understand an application structure and has an influence on reducing time for onboarding new team members (if these developers have a basic knowledge about Redux).
Additionally, Redux has excellent support for high-frequency data updates. In some kind of application, there are a lot of values refreshed every time. It could be many user interactions or maybe getting data from API. In this case, Redux could help.
Redux dev tools are useful and integrated with browsers. It is easy to use.
When to use Context?
We can find the answer in the React documentation directly. As is written in this article, Context was prepared for considering global, shareable data - like theme values or user authentication.
This build-in tool solves a huge problem: props drilling. The code where we have to pass down a lot of values and it still happens is not right to understand and maintain.
Context is a good way to share values between our components without using props every time, but these criteria should not be only one. If some values are needed on different levels of the components tree and for many elements, it will be a good idea to use context for this data. With Context, we have another way to share values and their changes. All components below the Context Provider are able to read this data, handle them, or rewrite. In some situations, it could be more comfortable than using other tools, especially for providing themes or caching data.
If you only think about keeping an application away from the props drilling problem, consider the component composition pattern (highlighted in React documentation about context).
Does React Context work more efficiently than Redux? Is it simpler, built-in, and easier to learn and has endless advantages? Not always. According to the quote of Sebastian Markbage, part of the React Team: Context is NOT designed for handling high-frequency updates. It doesn’t mean this feature will not work. Of course, it will, and you can decide to use it with success (especially in smaller projects).
Moreover, Context supports more finely by designing low-frequency updates (selected language, color theme) than others. On the other hand, Redux is better in the high-frequency update data field.
After reading this article, maybe you have one question - so, what is better? Redux or Context? The answer is not simple and easy.
First of all - it depends. Let’s take a look at the pros and cons. They are described above, separately for both tools.
The Context seems to be more comfortable and more flexible than Redux. You can choose and implement a custom wrapper for handling updates or call actions. Context with React Hooks is a robust feature that looks very well for maintenance and understanding data flow in the application. We do not need boilerplate code, the additional package (even for async actions), or extra files. Everything is built-in and ready to use.
Redux is a flux-based library directly for state management in applications. It's worth to mention a very active and helpful community and regular updates packages. Thanks to that combination, a lot of challenges and issues are quickly resolved and written down for the next users. A considerable part of the boilerplate code is no longer needed with Redux Toolkit, but it comes with costs. Less boilerplate code means the more logic is hidden. That approach may interfere with beginners to understand the system quickly.
Additionally, developers should understand new Redux terms, such as "store" or "dispatcher". Besides, middleware is required to invoke an asynchronous action.
Deciding which tool is more appropriate is not easy. Sometimes Redux is overkill for simple applications, even with Redux Toolkit. Context, on the other hand, is not a replacement for Redux. Sometimes for more complex applications with more developers, it can be easier to get started with Redux due to smoother maintenance.
In the end, "Which is better" should be understood as "what is better for our application and our team". It always depends on developers' experience, their knowledge of both solutions, and the use cases in individual projects.
Not satisfied with Redux or Context?
If you are not a big fan of the solutions described above (Redux or Context API), you can always try other ways. There are many libraries that support state management. Some of them are niche, others more common. Check out alternative tools for your application.