If you want to develop dynamic apps that respond well to user input, then it is incredibly important to be well-versed in State Management. Let’s explore some of the methods we can use to manage state in React.
One of the biggest challenges for modern web applications is balancing growth while maintaining logic between interface actions and data. In other words, React developers have to deal with the fact that, as applications become more complex, managing state will become increasingly challenging. That’s why it is so important to understand State Management in React and how we can use it to develop scalable and high-performance applications.
In React development, State Management is the process of tracking how your application data changes over time, maintaining data flows, and defining the state of data at any moment. The built-in state object in React components encapsulates the data where developers store assets that are persistent across component renderings.
With all of this in mind, we can start thinking of how React applications can model behaviors based on the state of the data. But that still leaves a few unanswered questions: How do you implement state in a React app? How do you read it? How do you change it?
One of the most notable methods to manage state in React applications is the one encouraged by the official React documentation: Hooks. Hooks are great on their own because they help developers write shorter, more readable code that is easy to share and maintain.
However, while it is true that hooks like useState and useReducer give a lot of usage and flexibility for Components, in most cases using them doesn’t prevent other problems like Prop Drilling (even using composition) or errors in shared data between different branches in the components tree.
To tackle this, the React team developed a new built-in tool called React-Context API and the useContext hook to complement it. Using both of these we should be able to wrap components with shared states together under the same “Context” while keeping access to its data. Simple, right? Now, we only have to deal with one more problem — we need to implement it all on our own.
There are several types of React libraries for State Management, but today we will focus on three: Contextual, Atomic and Hook-Based libraries. As expected, different state management libraries use different approaches to achieve the same or similar solutions. They also differ from each other in terms of library size, support for languages, documentation, API support, and more.
We can find two of the most popular state management libraries in this category: the React-Context API and Redux (RTK). The main goal of contextual libraries is to share the state through the entire app using Flux, an architectural pattern.
Let’s imagine an app that is defined like this:
In this graph, the Component A will:
However, a problem arises when, for example, the app needs to pass Info C from Component B to Component C. How could we solve this?
Well, the answer is a Context + Provider. Let’s take a look at how this works.
Here, we use a Provider (Wrapper) and a Context as base. The context itself has different definitions and implementation of functions to add, update, delete, and reset the state or parts of it. With this strategy, we can get direct access to the same data in different components and use the functions (or actions) to add, update, delete, or reset the state whenever the app requires. There is a small price to pay, however: we can only access the data if the components are wrapped by the provider.
Atomic libraries like Recoil and Jotai follow similar principles to contextual state managers. One of the characteristics that differentiates them is how they solve that little caveat in data accessibility we mentioned earlier. In this case, each data value is represented by an “atom”, a simple variable (like useState) that can be easily manipulated using hooks and helps us access the state outside of it.
While all of this might sound great, React developers should be careful of where and when atoms are being manipulated. It is not rare to cause issues in the data flow, and therefore, errors in the app.
Finally, let’s go over Hook-Based libraries. To put it simply, Hook-Based libraries combine the previous two types, where instead of context or atoms, it creates stores that basically work like context, but that don’t require wrapping the components or parts of the app with a Provider for access or data manipulation. Just creating the store with the expected data structure and defining how it will be manipulated creates a state that’s easy to use with hooks or directly in parts of the app outside components. Here, we’ll find libraries like Zustand.
After taking this trip around many of the different options we have for state management, it’s time to take start evaluating which ones tick the most boxes for each use case.
All solutions are valid, what we need to do is find which one accommodates the definition of the application, what is more, comfortable for the team, how important is scalability, and what kind of state management works better with your app. Keep in mind that two or more state management libraries can coexist at the same time, as long as your team keeps a very good definition of what each one is used for in specific situations. In other words, whatever tool you choose, taking into account your goal and the scope of the application will be the key to identifying the best state management tool for you.
We’d love to learn more about your project.
Engagements start at $75,000.