In this article, we provide a concise overview of state management, the Context API, and Flux architecture. Our emphasis is on exploring the pros and cons of React Context and Redux to recap and clarify the best tool for a React app.
Understanding React - Part 2
This article is part 2 in a series about the Redux vs. Context framework and testing, aiming to help you make the right decision for your app.
On the other hand, the latest version of React introduces the new Context API. It appears that both of these tools could share similar responsibilities in an application like Redux. But is this assertion accurate?
In this article, we provide a brief overview of state management and Flux architecture. We then delve into the advantages and disadvantages of Redux and the Context API in 2020. Finally, we recap and clarify the best situations to use these tools.
Application state management is crucial in medium and large projects. While it can be useful in smaller, more manageable projects, sometimes we can handle it without special libraries or patterns.
Usually, we explain state management for front-end applications as a kind of logic that keeps and refreshes current data. For example, whether the radio button is checked or not, or if the user is authenticated. More abstractly, it means taking care of complete business transactions - maintaining user interface inputs and possibly synchronizing data between pages, back-end, and front-end parts.
Additionally, it is an excellent way to separate clean component rendering (or view) from the business layer.
From a more React-oriented point of view, proper state management prevents us from passing a lot of props from top-level elements to destination grand-grandchildren. In some cases, we need a global state where all components can access essential data. However, it doesn’t mean that everything should be universal. Some local variables are available only for one element and perhaps its children, so it is good to keep them localized (for example, whether local field validation is visible or not).
Before delving into React-Redux, let's provide a brief overview of the Flux concept, popular in front-end applications, especially those developed with React or Vue. Facebook recommends the Flux architecture for creating Single Page Applications (SPAs), which is why many libraries support this data flow to the React app.
Flux is based on four parts of the application:
This part solely manages the state, housing values from both the UI and business layer. In the application, there should be only one "source of truth": stores (and there can be many stores). It is crucial to remember that a store manipulates the state (the data keeper). The store manages this data to handle business transactions.
So, how is data changed? 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 includes a type field for the action name (id) and payload for additional data.
Action Creators are small but powerful assistants in providing actions. It is a good practice to encapsulate code. Instead of writing the same lines every time to dispatch the same action, we can prepare a function that returns its type and perhaps accepts a payload.
This layer is a single object for sharing actions among all stores in the app. The dispatcher broadcasts the called action.
• View (Presentation and Container)
View refers to a UI element. At this point, the component should render elements and handle user actions (like clicking buttons, typing text, or drag & drop). In case of changes, the view is re-rendered.
• Presentation Views
All values are passed through props. These components should not directly call the store, and the same goes for actions – they cannot have interactions with the dispatcher. Everything, even functions, comes from props.
• Container Views
These views are more powerful than the presentation parts. After a user action, containers dispatch actions, so they are connected to the dispatcher and the stores. The Container Views' task is to notice store changes and populate data for presentation elements.
Redux remains the most popular choice for state management as a flux-based tool.
It was first released in June 2015, two years after the initial launch of React. The original authors of this solution are Dan Abramov and Andrew Clark.
Follow the rules to implement the expected actions for this library:
1. Maintain only one central store. Its values are immutable and cannot be changed.
2. The steps for updating the global state are encapsulated within reducer functions, where the new state is returned as the result of their operations.
3. Utilize subscriptions to obtain refreshed values for data.
4. Dispatch actions to invoke reducer functions.
• Widely used (popularity) - many issues are resolved by the community
• Redux Toolkit - an impressive new feature to reduce boilerplate code
• Designed for frequently updated (refreshed) data
• Good React Redux package for integration with React
• Improved debugging - there is an option to log state and actions
• Code organization - applications with Redux typically have a similar architecture, making it easier for experienced developers to understand the structure of the next project
• Server-side rendering is available with Redux
• Not built-in to React (increases the final bundle size)
• May be misleading for beginners (due to a lot of hidden logic), even with Redux Toolkit
• Requires more setup than Context API (and involves more terms to understand)
• Reusing components is harder because some data comes from the global state, not from props
• Middleware for asynchronous tasks
A little curiosity about this tool: according to one section of its documentation, React Redux uses the Context API internally to broadcast data to nested elements.
Since React v16.3.0, we can use not only new lifecycle methods but also the Context API, which was introduced with this version. Before this update, React had experimental support for this feature, but now there is a more efficient, new context API.
What is Context? It is a smart built-in feature designed to solve problems related to sharing data between nested (not directly connected) components through the Context API.
• The built-in React tool has not influenced the final bundle size and is integrated by design with every npm package
• Easier to understand and handle for beginners compared to the Redux data flow
• Excellent for more static data - not updated as frequently as in Redux
• Only a little setup is required - create a context and sometimes a wrapper component
• Well-documented part of React
• A lot of local contexts to handle separate logic tasks can be in the application
• Context API is not designed for frequently refreshed or changed data
• There could be more challenging maintenance in more complex frontend applications, especially if custom solutions and helpers are in use
• Reusing components is more challenging because some data comes from the context, not always from props
When to use Redux?
Managing the state of complex applications seems to be an excellent task for Redux. It is a powerful tool that handles all aspects of this part. Our app, with this library applied, could support server-side rendering, which is sometimes an essential feature— the same goes for debugging.
From the architectural viewpoint, Redux helps us keep project folders and files in order, making our app readable for further development. This tool suggests splitting code into logical parts, such as reducers or actions, allowing developers to understand the application's structure. It also influences reducing the time for onboarding new team members, assuming these developers have a basic knowledge of Redux.
Additionally, Redux has excellent support for high-frequency data updates. In some types of applications, many values are refreshed every time, whether through user interactions or obtaining data from APIs. In this case, Redux could be particularly helpful.
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 DevTools are useful and integrated with browsers, making them 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 in the app.
This built-in tool solves a significant problem: props drilling. Code where we have to pass down a lot of values, and it still happens, is not easy 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 the only ones. If some values are needed on different levels of the component 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 them. In some situations, it could be more comfortable than using other tools, especially for providing themes or caching data.
If you're only thinking about solving the prop drilling problem, consider the component composition pattern (highlighted in the React documentation about context).
Does React Context API work more efficiently than Redux? Is it simpler, built-in, and easier to learn, with 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 successfully, especially in smaller projects.
Moreover, Context excels in supporting more finely designed low-frequency updates (like selected language or color theme) than others. On the other hand, Redux performs better in the high-frequency update data field.
After reading this article, you might be left with one question: What is better for your future app - Redux or Context API? The answer is neither simple nor easy.
First and foremost, it depends. Let’s examine the pros and cons, which have been detailed above for both tools.
Context appears to be more comfortable and flexible than Redux. You can choose and implement a custom wrapper for handling updates or call actions. Context, combined with React Hooks, is a robust feature that contributes well to the maintenance and understanding of the data flow in the application. There's no need for boilerplate code, additional packages (even for async actions), or extra files - everything is built-in and ready to use.
Redux, on the other hand, is a flux-based library designed explicitly for state management in applications. It boasts a very active and helpful community, along with regularly updated packages. Thanks to this combination, many challenges and issues are quickly resolved and documented for future users. Although Redux Toolkit reduces a significant portion of boilerplate code, it comes with its costs. Less boilerplate code means more hidden logic, potentially posing a challenge for beginners to quickly grasp the system. Additionally, developers need to understand new Redux terms, such as "store" or "dispatcher," and middleware is required to invoke asynchronous actions.
Deciding which tool is more appropriate is not easy. Redux can be overkill for simple applications, even with Redux Toolkit. On the other hand, Context is not a direct replacement for Redux. For more complex applications with larger development teams, starting with Redux might be easier due to smoother maintenance.
In the end, the question of 'Which is better?' should be reframed as 'What is better for our application and our team?' It always depends on the developers' experience and their knowledge of both solutions, as well as 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 explore other options. Many libraries support state management, ranging from niche solutions to more commonly used ones. Consider exploring alternative tools for your application.
If you need advice or consultation, do not hesitate to contact us. We are more than happy to help.
Author: Marta Zażlak