We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to apply for this job!

Login or register
to publish this job!

Login or register
to save this job!

Login or register
to save interesting jobs!

Login or register
to get access to all your job applications!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Engineers who find a new job through Ai Works average a 15% increase in salary 🚀

Blog hero image

State Management Battle in React 2021: Hooks, Redux, and Recoil

Blessing krofegha 7 April, 2021 | 9 min read

Introduction:

Over the years, the massive growth of React.JS has given birth to different state management libraries, amongst other things. The state management libraries available in React at our disposal at the time of this article are enormous. Therefore, knowing what state management library to choose for a particular project not to get carried away by the noise and news from the React community is a significant factor in facilitating the development of an application. Some developers tackle the challenge by using React Hooks; others combine them with application state management libraries like Redux or the newly release Recoil.

In this article, we will discuss state management using Redux, Hooks, and Recoil in a typical React application and their best uses cases. We will also try to answer questions like:

  • What metric to consider before choosing a state management library?

Note: This tutorial will be beneficial to readers interested in developing React application that requires a state management library. This article isn’t an intro to state management in React. It requires a basic understanding of React, hooks, and a bit of Redux; hence, if you’re starting with React and state management in React, please go through these basics before beginning this tutorial 😎.

What’s State in a Nutshell?

State management is simply a way to engender communication and sharing of data across components. It creates a concrete data structure to represent your app's State that you can read and write. Since React 16.8, every React component, whether functional or class, can have a state. In the simplest definition, State is a JavaScript object that represents the part of a component that can change based on a resultant action of a user. You could also say states are simply the memory of a component. When a user performs an action in a typical React app, changes occur in the component's state. While this isn't bad, it quickly becomes a problem if the app begins to scale; hence, such an app's complexity makes it extremely difficult to keep track of all dependencies.

To answer the introduction question, suppose we are building an eCommerce application; in an app like this, just about every element can be a component – the shopping cart, the buttons, the view cart session, checkout, login bar, etc. In this app, just a single user action of adding to the cart can influence many other components by:

  • changing the State of the cart component itself,
  • adding the cart to the user's cart history,
  • checkout product items.

And that's to mention only a few from the other plenty stuff that we could add to the eCommerce app. If the engineers in charge do not consider scalability while developing the app, they might soon quickly run into many bugs and problems in the long run. Constantly debugging and revamping an app like this could eventually be a pain.

The above scenarios show us the importance of the state in a typical React application. In managing the state in this application, we could use any library of our choice; they would still get the job done regardless.

Usually, the state will have to be lifted to the closest parent component and the next until it gets to an ancestor common to both components that need the state, and then it is passed down. This process can be overwhelming and makes the state challenging to maintain. Often it might warrant you to pass data to components that do not even need it.

State management gets messy as the app grows bigger. That is why you need a state management tool like Redux, Recoil, making it easier to maintain these states. In the following sections, we would practically look at all the state management libraries(Redux, Hooks, Recoil), their uniqueness, and what to consider before going for any of them.

Redux

The first on our list is Redux; It has been around for a while, pretty much the first react-based state management library. The state management library Redux was created to address the problem in our eCommerce app. It provides a JavaScript object called the store, which, once set up, includes all states in your application and updates them when necessary. Here is a simplified visualization of how Redux works.

Redux workflow

Perhaps you're asking, why is Redux often used with React? The reason from my experiences is because, Redux handles state updates in response to user's actions, especially in UI; Asides from that, Redux can be used as standalone state management from any framework.

When to use Redux?

Redux is one of the most popular React state management libraries as of the time of this article. In this section, we would look closely into when to use Redux in an application.

Firstly, Redux allows you to manage your app's state in a single place and keep changes in your app more predictable and traceable. It makes occurring changes in your app easier to figure out. Unfortunately, all of these benefits come with specific constraints and tradeoffs. Frequently, developers feel using Redux adds up some boilerplate code, making little things seemingly overwhelming; however, that depends solely on the app's architectural decision.

One of the easiest ways to know when you genuinely need to use Redux is when managing state locally begins to look messy. As the application grows, so does state sharing across components gets tedious. At that point, you'd now start looking for ways to make the process hassle-free. In the next section, we would look at why we should Redux with React.

Why use Redux?

Using Redux with React takes away the hassle of lifting upstate, making it easier for you to trace which action causes any change, hence simplifying the app and making it easier to maintain. Let's take a look at some tradeoffs that come with using Redux for state management.

Community Support As the official binding library for React and Redux, React-Redux encompasses a large community of users. that makes it easier to ask for help, learn about best practices, use libraries that build on React-Redux, and reuse your knowledge across different applications. It's the highest stared React state management library on Github.

Enhances Performance React Redux assures performance optimization so that only the connected component only re-renders when it needs to; hence keeping the app's state global wouldn't result in any problem.

Redux makes the state predictable In Redux, the state is always predictable. If the same state and action move to a reducer, it will obtain the same result because reducers are pure functions. The state is also immutable and is never changed. It makes it possible to implement arduous tasks like infinite undo and redo. It is also possible to implement time travel — that is, the ability to move back and forth among the previous states and view the results in real-time.

State persistence on Local Storage Persisting some of the app’s state on local storage and restoring it after a refresh is possible. It makes storing things like cart data on local storage really awesome.

Server-side rendering We can also use redux for server-side rendering. With it, you can handle the app's initial render by sending the state of an app to the server along with its response to the server request.

Redux is maintainable Redux is strict about how code should get designed, making it easier for someone abreast with Redux to understand any Redux application structure. It generally makes it easier to maintain. It also helps you segregate your business logic from your component tree. For large-scale apps, it's critical to keep your app more predictable and maintainable.

Debugging is made easy Redux makes it easy to debug an application. By logging actions and state, it is easy to understand coding errors, network errors, and other forms of bugs that might come up during production. Besides logging, it has excellent DevTools that allows you to time-travel actions, persists actions on page refresh, etc. For medium- and large-scale apps, debugging takes more time than actually developing features.

While Redux has its benefits, it doesn't warrant that you add Redux in all your apps. Your application can work well without Redux.

Recoil

Recoil seems to be the newest tool on the state management community— A community with tons of excellent libraries like Context, Mobx, and Redux, etc.

Before going into details about Recoil, I'd like to point out that this new state management library is not the "official" state management library for React. However, the record shows that it was built and released by engineers from Facebook's team, the React creator. But then, just as Redux isn't an official state management library for React, Recoil isn't either but may gain mass adoption by React enthusiasts if it proves valuable to the React ecosystem at large.

The primary problem Recoil solves

While it has its learning curve, it still solves the same as most other state management libraries: global state management. After using Recoil for only a short while, here are the distinctions I think Recoils comes very handy.

React-like approach and simplicity The simplicity of Recoil is second to none, hence the reason it's on this list. You could build whatever app you build with Recoil as you could make just as with Redux or MobX. However, Recoil feels like using a global version of React's useState. It also supports Concurrent Mode, a huge plus (this is still in the works at the time of writing).

Easy Learning Curve Recoil doesn't impose a strict learning curve as Redux and Mobx do. They aren't so much to learn asides from Atom and Selectors, which are easy to understand.

App-wide observation Similar to other state management libraries, Recoil handles app-wide state observations well. Other benefits of using Recoil includes;

  • Boilerplate-free API
  • Distributed and incremental state definition

Recoil's central core concepts are Atoms and Selectors; covering this section is beyond the scope of this article. However, you can check their documentation for an in-depth overview.

When to use Recoil

In less than two years of its release, Recoil has grown so much that it has about 12k plus stars on Github at the time of this article. Asides from that, it's gradually gaining momentum and mass adoption amongst React enthusiasts and the React community at large. Personally speaking, the only reason I have used Recoil in any of my projects is when I don't intend to have so much Redux boilerplate in my codebase. I have used Recoil on production once, and nothing terrible has happened; everything still works very well to date.

So when to use Recoil might solely depend on your app's architecture decision, and if you are a lover of simplicity like myself, you might jump into using Recoil 😎.

Using React Hooks

Hooks is one of the most outstanding features ever added to the React library since its creation. Hooks brought ‘state’ to functional components. Now, functional components can create and manage local states on their own, just like class components. Anyone already into React should get familiar with React hooks, including useState, useEffect, and useReducer, etc. This section will discuss how handy React Hooks can be standalone without intermeddling with any external state management library.

You could use React Hooks as your primary state management tool without any library, but this will depend on your experience and understanding of React hooks.

They are powerful on their own and can accomplish almost anything an external library could do.

To some extent, other state management tools have a few advantages. Still, their procedures make it challenging to get started. Like in the case of Redux, some boilerplate code is needed to get it working in our application; hence, it introduces unnecessary complexity. On the other hand, with the useContext API and React Hooks, there is no need to install external libraries to get our app working. It makes it a much simpler, more straightforward way to handle global state management in React applications.

Note: Assuming you’re already familiar with useState, we would look into two hooks that aid the process of state management in React.

The useReducer Hook

The useReducer Hook came with React 16.8. Just like the reduce() method in JavaScript, the useReducer Hook receives two values as its argument — a reducer function and an initial state — and then returns a new state:

const [state, dispatch] = useReducer((state, action) => {
  const { type } = action;
  switch(action) {
    case 'action description':
      const newState = // do something with the action
      return newState;
    default:
      throw new Error()
  }
}, []);

In the snippet above, we’ve defined our state and a corresponding method, dispatch, handling it. When we call the dispatch method, the useReducer() Hook will perform an action based on the type that our method receives in its action argument:

...
return (
  <button onClick={() =>
    dispatch({ type: 'action type'})}>
  </button>
)

useContext

This hook is used to get the current context of a Provider. To create and provide a context, we use the React.createContext API.

const myContext = React.createContext()

We put the root component between the myContext Provider:

function App() {
    return (
        <myContext.Provider value={900}>
            <Root />
        </myContext.Provider>
    )
}

To consume the value provided by the <myContext.Provider></myContext.Provider> we use the useContext hook.

function Root() {
    const value = useContext(myContext)
    return (
        <>
            <h3>My Context value: {value} </h3>
        </>
    )
}

Using useReducer and useContext

Using useContext together with useReducer takes the component co-located state management on another level. Suddenly we can pass the state container created by useReducer and its dispatch function to any component from any top-level component. It can also be the most top-level component to make the state "global." It's also possible to pass things down only using React props, but React's Context API makes your state and dispatch function available anywhere without explicitly passing everything down the component tree.

Conclusion

In this article, we tried to cover the most trending state management tools for React in 2021, how they play an essential role in React state management, and when to use them in a project. I'd like to know what your experiences are in managing state in a typical React application.

Resources

Author's avatar
Blessing krofegha
Blessing Krofegha is a Software Engineer Based in Lagos Nigeria, with a burning desire to contribute to making the web awesome for all, by writing and building solutions.
    Elixir
    React Native
    React
    AWS
    JavaScript

Related Issues

WorksHub / cljc-css-loader
  • 1
  • 5
  • Intermediate
  • JavaScript
  • $50
cosmos / gaia
  • Open
  • 0
  • 0
  • Intermediate
  • Go
cosmos / gaia
  • Started
  • 0
  • 2
  • Intermediate
  • Go
cosmos / ibc
  • Open
  • 0
  • 0
  • Intermediate
  • TeX
cosmos / ibc
cosmos / ibc
  • Started
  • 0
  • 1
  • Intermediate
  • TeX
viebel / klipse-clj
viebel / klipse-clj
  • Started
  • 0
  • 4
  • Intermediate
  • Clojure
viebel / klipse
  • Started
  • 0
  • 1
  • Intermediate
  • Clojure
viebel / klipse
  • 1
  • 0
  • Intermediate
  • Clojure

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through Ai Works average a 15% increase in salary.

Start with GitHubStart with Stack OverflowStart with Email