---
title: "Redux vs Recoil - Comparing Two React State Libraries | CoderPad"
description: "The React state can be managed directly in-app or via state management libraries. This article compares two state management libraries, Redux and Recoil, and helps you choose which is best for your application's needs."
canonical: "https://coderpad.io/blog/development/redux-vs-recoil/"
last_modified: "2026-04-15 16:21:08"
---
[Back to blog](https://coderpad.io/blog/)

# Redux vs Recoil – Comparing Two React State Libraries

October 10, 2022 7 Minute Read

By Victory Tuduo

[Development](https://coderpad.io/blog/development/)

State management is indispensable when building medium to large-scale React projects due to the large number of components that must be able to communicate with each other efficiently. Also, these large projects may have logic implemented on the front end that requires a global application state.

Luckily, in addition to the state management solutions and features shipped with React, there are specialized libraries built for managing state in React applications.

We’ll take look at two popular options out of the many libraries out there—Redux and Recoil—and show you how to implement them.

## What is a state management library?

A state management library provides a structure and functionalities for modeling and accessing the global application state. Data is centralized in one location, usually a “store” where every component can access that data, set values, and monitor for changes.

Without state management, components will be unable to get data contained in other components without the use of something like “ [prop drilling](https://kentcdodds.com/blog/prop-drilling) ”.

[![Diagram of application components without state management](https://coderpad.io/wp-content/uploads/2022/10/img_633f213c96786-1024x576.png)](https://coderpad.io/wp-content/uploads/2022/10/img_633f213c96786.png)

With state management, however, every component can have access to and write to the same application state.

[![Diagram of application components with state management](https://coderpad.io/wp-content/uploads/2022/10/img_633f213f0c748-1024x576.png)](https://coderpad.io/wp-content/uploads/2022/10/img_633f213f0c748.png)

Next, let’s look at how we can use state management libraries like Redux and Recoil to manage state in our React applications.

## Redux

According to the [Redux docs](https://redux.js.org/tutorials/fundamentals/part-1-overview#what-is-redux), “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.

Here are a few things the [Redux documentation](https://redux.js.org/tutorials/fundamentals/part-1-overview) wants us to know before we proceed.

### Why use Redux?

Redux manages the “global” application state – a state that is accessible across many parts of your application.

The patterns and tools provided by Redux make it easier to understand when, where, why, and how the state in your application is being updated, and how your application logic will behave when those changes occur.

Redux is more useful when:

- The app state is needed in numerous locations throughout the app and is regularly updated over time.
- The logic to update that state may be sophisticated.
- The app has a medium-to-large scaled codebase and might be worked on by many people.

Not all applications require Redux. Spend some time considering the type of app you’re creating and deciding which tools would be most helpful in resolving the issues you’re working on.

Now that that’s out of the way, let’s set up Redux in a React application.

### Redux components and terminology

Redux Store, Action, and Reducer are the three main parts of Redux.

Redux Store is the “brain” of our state management structure.

It manages the state and dispatches Actions

Dispatch is a method in the Redux store. The state can only be updated by calling`store.dispatch()`and providing an action object.

Action refers to the commands passed to the Reducers, which can be interpreted by it. It stores information regarding the user’s actions. There is a type and a payload in the action. The payload contains the actual data provided by the action, whereas the type is only a string with the action name.

Reducers are functions that read the instructions sent by the Action and update the store using the state. Reducers specify how the application’s state will change in response to the actions sent to the store.

We will use a counter application as a case study as we move on, to discuss how to set up and use Redux in an app.

### Install and setup Redux

Add Redux Toolkit and React Redux packages to your project:

```
npm install @reduxjs/toolkit react-reduxCode language: CSS (css)
```

### Create a Redux Store

Create a new file –`./src/store/index.js.`

```
// ./src/store/index.js

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {},
})Code language: JavaScript (javascript)
```

Here, we import the`configureStore`API from Redux Toolkit and create an empty Redux store, and export it.

This creates a Redux store with an empty`reducer`function. Next, we’ll have to make the store accessible for the rest of our React application.

### Provide Redux store to the application

We can make the newly created store available to our React components by importing and wrapping the React Redux`<Provider>`over the application. We’ll do all that in the`./src/index.js`file.

```
./src/index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

// import Provider
import { Provider } from "react-redux";

// import store
import store from "./store/index";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(

  // wrap application with Provider
  <Provider store={store}>
    <StrictMode>
      <App />
    </StrictMode>
  </Provider>
);Code language: JavaScript (javascript)
```

### Create Redux state slice(s)

We’ll create redux state slices for two pieces of state:`booksSlice`and`savedBooksSlice`.

Creating a slice requires a string name to identify the slice, an initial state value, and one or more reducer functions to define how the state can be updated. Once a slice is created, we can export the generated Redux action creators and the reducer function for the whole slice.

First, create a slice for our books array state in a new file:`./src/store/books/booksSlice.js`:

```
// ./src/store/books/booksSlice.js

import { createSlice } from "@reduxjs/toolkit";
export const booksSlice = createSlice({
  name: "books",
  initialState: {
    value: [{
        id: "001",
        title: "Harry Potter and the Deathly Hallows",
        price: 5.0,
        rating: "5.0"
      },
      {
        id: "002",
        title: "Harry Potter and the Goblet of Fire",
        price: 5.0,
        rating: "4.8"
      }
    ]
  },
  reducers: {
    set: (state, action) => {
      return action.payload;
    }
  }
});

// Action creators are generated for each case reducer function
export const { set } = booksSlice.actions;

export default booksSlice.reducer;Code language: JavaScript (javascript)
```

Here, we import the`createSlice`API from Redux Toolkit and export`booksSlice`, and define the`name`,`initialState`, and`reducers`using`createSlice`.

Next, we’ll create a state slice for`savedBooks`. Create a new file:`./src/store/books/booksSlice.js`:

```
// ./src/store/books/booksSlice.js

import { createSlice } from "@reduxjs/toolkit";
export const savedBooksSlice = createSlice({
  name: "savedBooks",
  initialState: [],
  reducers: {
    add: (state, action) => {
      // get the payload object from by destructuring the action parameter
      //  assign value of payload to book
      const { payload: book } = action;
      return [...state, book];
    },
    remove: (state, action) => {
      // get the payload object from by destructuring the action parameter
      //  assign value of payload to bok
      const { payload: book } = action;
      const bookIndex = state.findIndex((x) => x.title === book.title);
      // if no match, return the previous state
      if (bookIndex < 0) return state;
      // avoid mutating the original state, create a copy
      const stateUpdate = [...state];
      // then splice it out from the array
      stateUpdate.splice(bookIndex, 1);
      return stateUpdate;
    }
  }
});

// Action creators are generated for each case reducer function
export const { add, remove } = savedBooksSlice.actions;

export default savedBooksSlice.reducer;Code language: JavaScript (javascript)
```

Next, we’ll make these state slices global by importing them into our store.

### Add slice reducers to the store

Now, we need to import the reducer functions from the state slices and add it to our store. Back in`./src/store/index.js`:

```
// ./src/store/index.js

import { configureStore } from "@reduxjs/toolkit";
import savedBooksReducer from "./books/savedBooksSlice";
import booksReducer from "./books/booksSlice";
export default configureStore({
  reducer: {
    books: booksReducer,
    savedBooks: savedBooksReducer
  }
});Code language: JavaScript (javascript)
```

Now that we’ve configured our store, let’s use our state in our components

### Use Redux state and actions in React components

Now we can use the React Redux hooks to let React components interact with the Redux store. We can read the data from the store with`useSelector`, and dispatch actions using`useDispatch`.

First, in`./src/SavedBooks.js`component, we’ll use`useSelector`to read the`savedBooks`data.

```
import React from "react";
import { useSelector } from "react-redux";
export function SavedBooks() {
  const savedBooks = useSelector((state) => state.savedBooks);
  // function to get total price from savedbooks array
  const getTotalPrice = (savedBooks) => {
    const totalPrice = savedBooks.reduce(
      (totalCost, item) => totalCost + item.price,
      0
    );
    return totalPrice;
  };
  return (
    <header>
      <p> No. of Books: {savedBooks.length} </p>
      <p> Total price: ${getTotalPrice(savedBooks)} </p>
    </header>
  );
}Code language: JavaScript (javascript)
```

Next, we’ll use`useSelector`and`useDispatch`to read and update the`books`and`savedBooks`state respectively in the`./src/Books.js`component.

To dispatch the actions`add`and`remove`we need to import the actions and use the`useDispatch`hook provided by react-redux to dispatch our actions.

```
// ./src/Books.js

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { add, remove } from "./store/books/savedBooksSlice";
export function Books() {
  const dispatch = useDispatch();
  const books = useSelector((state) => state.books.value);
  return (
    <div>
      <ul className="Books">
        {books.map((book) => {
          return (
            <li className="book" key={book.title}>
              <header>
                <h3> {book.title} </h3>
                <p>Rating: {book.rating} </p>
                <p> ${book.price} </p>
              </header>
              <button onClick={() => dispatch(add(book))}> Add </button>
              <button onClick={() => dispatch(remove(book))}> Remove </button>
            </li>
          );
        })}
      </ul>
    </div>
  );
}Code language: JavaScript (javascript)
```

Great! Now, our app works with Redux!

Next, we’ll explore another interesting state management library – Recoil

## Recoil

Recoil, according to [its docs](https://recoiljs.org/docs/introduction/core-concepts/#:~:text=Overview%E2%80%8B,state%20either%20synchronously%20or%20asynchronously.), is a newer state management library built by the Facebook open-source community. It’s best explained by looking at the core concepts from the docs, which we recap below.

### Recoil components and terminology

Recoil lets you create a data-flow graph that flows from atoms (shared state) through selectors (pure functions) and down into your React components. Atoms are units of state that components can subscribe to. Selectors transform this state either synchronously or asynchronously.

Atoms are units of state. They’re updatable and subscribable: when an atom is updated, each subscribed component is re-rendered with the new value.

A selector is a pure function that accepts atoms or other selectors as input. When these upstream atoms or selectors are updated, the selector function will be re-evaluated. Components can subscribe to selectors just like atoms, and will then be re-rendered when the selectors change.

You can [find out more from the documentation](https://recoiljs.org/docs/introduction/core-concepts).

Let’s move on and see how we can use Recoil in our React application.

### Install and set up Recoil

To install the latest stable version, run the following command:

```
npm install recoil
#or
yarn add recoilCode language: CSS (css)
```

Now that we have Recoil installed, we have to add`RecoilRoot`to our app’s root component in`./src/App.js`:

```
// ./src/App.js

import { Books } from "./Books";
import { SavedBooks } from "./SavedBooks";

// import RecoilRoot
import { RecoilRoot } from "recoil";

export default function App() {
  return (
    <RecoilRoot>
      <div className="App">
        <SavedBooks />
        <Books />
      </div>
    </RecoilRoot>
  );
}Code language: JavaScript (javascript)
```

Next, we’ll create our atoms which will contain our`books`and`savedBooks`state.

### Create books state atom

Create a new file`./src/atoms/books.js`:

```
// ./src/atoms/books.js

import { atom } from "recoil";
const booksState = atom({
  key: "books",
  default: [{
      id: "001",
      title: "Harry Potter and the Deathly Hallows",
      price: 5.0,
      rating: "5.0"
    },
    {
      id: "002",
      title: "Harry Potter and the Goblet of Fire",
      price: 5.0,
      rating: "4.8"
    }
  ]
});

export { booksState };Code language: JavaScript (javascript)
```

### Create savedBooks atom state

Create another file`./src/atoms/savedBooks.js`:

```
// ./src/atoms/savedBooks.js

import { atom } from "recoil";
const savedBooksState = atom({
  key: "savedBooks",
  default: []
});
export { savedBooksState };
Code language: JavaScript (javascript)
```

In order to read from and write to an atom, Components should use`useRecoilState()`. This means, to use the`books`atom state in the`Books`component, we simply import`useRecoilState()`and`booksState`.

To read from an atom, we use`useRecoilValue`:

```
// ./src/Books.js

import React from "react";
import { useRecoilValue } from "recoil";
import { booksState } from "./atoms/books";

export function Books() {
  const books = useRecoilValue(booksState);

  return (
    <div style={{ border: "1px solid" }}>
      <ul className="Books">
        {books.map((book) => {
          return (
            <li className="book" key={book.title}>
              <header>
                <h3> {book.title} </h3>
                <p>Rating: {book.rating} </p>
                <p> ${book.price} </p>
              </header>
            </li>
          );
        })}
      </ul>
    </div>
  );
}Code language: JavaScript (javascript)
```

Also, we can do the same thing in our`savedBooks`component –`./src/SavedBooks.js`:

```
// ./src/SavedBooks.js

import React from "react";
import { useRecoilValue } from "recoil";
import { savedBooksState } from "./atoms/savedBooks";

export function SavedBooks() {
  const savedBooks = useRecoilValue(savedBooksState);
  // function to get total price from savedbooks array
  const getTotalPrice = (savedBooks) => {
    const totalPrice = savedBooks.reduce(
      (totalCost, item) => totalCost + item.price,
      0
    );
    return totalPrice;
  };
  return (
    <header style={{ border: "1px solid", marginBottom: "6px" }}>
      <p> No. of Books: {savedBooks.length} </p>
      <p> Total price: ${getTotalPrice(savedBooks)} </p>
    </header>
  );
}Code language: JavaScript (javascript)
```

Now that we know how to read our state, how do we modify it?

To do that we have to do a few things. Let’s bring the`add`and`remove`functions into our`Books`component:

```
// .src/Books.js

import React from "react";
import { useRecoilValue, useSetRecoilState } from "recoil";
import { booksState } from "./atoms/books";
import { savedBooksState } from "./atoms/savedBooks";
export function Books() {
  const books = useRecoilValue(booksState);
  const setSavedBooks = useSetRecoilState(savedBooksState);
  const add = (book) => {
    //  assign value of payload to bok
    setSavedBooks((state) => {
      return [...state, book];
    });
  };
  const remove = (book) => {
    //  assign value of payload to bok
    setSavedBooks((state) => {
      const bookIndex = state.findIndex((x) => x.title === book.title);
      // if no match, return the previous state
      if (bookIndex < 0) return state;
      // avoid mutating the original state, create a copy
      const stateUpdate = [...state];
      // then splice it out from the array
      stateUpdate.splice(bookIndex, 1);
      return stateUpdate;
    });
  };
  return (
    <div style={{ border: "1px solid" }}>
      <ul className="Books">
        {books.map((book) => {
          return (
            <li className="book" key={book.title}>
              <header>
                <h3> {book.title} </h3>
                <p>Rating: {book.rating} </p>
                <p> ${book.price} </p>
              </header>
              <button onClick={() => add(book)}> Add </button>
              <button onClick={() => remove(book)}> Remove </button>
            </li>
          );
        })}
      </ul>
    </div>
  );
}Code language: JavaScript (javascript)
```

In the code above, you can see that we assigned`const setSavedBooks = useSetRecoilState(savedBooksState)`.

With this, we can modify our`savedBooksState`atom which we did by using`setSavedBooks`within our`add`and`remove`functions.

### Using selectors

Remember our`getTotalPrice`function which dynamically gets the total price of saved books? We’ll use a selector to dynamically render the total price of the items in the`savedBooks`array.

First, we have to create a new file`./src/selectors/totalPrice.js`:

```
// ./src/selectors/totalPrice.js

import { selector } from "recoil";
import { savedBooksState } from "../atoms/savedBooks";
const totalPrice = selector({
  key: "getTotalPrice",
  get: ({ get }) => {
    const savedBooks = get(savedBooksState);
    const totalPrice = savedBooks.reduce(
      (totalCost, item) => totalCost + item.price,
      0
    );
    return totalPrice;
  }
});
export { totalPrice };Code language: JavaScript (javascript)
```

The`totalPrice`selector keeps track of`savedBooksState`and re-runs if there are any changes.

Back in the`SavedBooks`component, we import our selector and use it.

```
// ./src/SavedBooks.js

import React from "react";
import { useRecoilValue } from "recoil";
import { savedBooksState } from "./atoms/savedBooks";
import { totalPrice } from "./selectors/totalPrice";

export function SavedBooks() {
  const savedBooks = useRecoilValue(savedBooksState);
  const getTotalPrice = useRecoilValue(totalPrice);
  return (
    <header>
      <p> No. of Books: {savedBooks.length} </p>
      <p> Total price: ${getTotalPrice} </p>
    </header>
  );
}Code language: JavaScript (javascript)
```

There we go! We’ve successfully used Recoil for state management in our React application.

## Other state libraries to consider

Between this article and [Global State Management in React without a Library](https://coderpad.io/blog/development/global-state-management-react/), you’ve learned how to handle state in React apps using a variety of methods and tools, including Redux and Recoil for medium to big projects and Hooks and Context API for small to medium projects.

Nevertheless, the React ecosystem provides a wide range of state libraries. The majority of them were developed and constructed with a particular idea and use case in mind, so if you want to use any of them, you’ll probably have a good reason for doing so.

A few of them include:

- [Zustand](https://github.com/pmndrs/zustand) – a state-management solution that is compact, quick, and scalable. It is particularly concerned with module state. This library is independent and is based on Hooks.
- [Jotai](https://github.com/pmndrs/jotai#readme) – a simple and extensible React state management library that offers a simple API. It is designed for computed values and asynchronous actions to state, and it supports TypeScript.
- [Mobx](https://mobx.js.org/README.html) – an independent stage-management library that isn’t platform-specific, thus it can be used outside of React. It applies functional reactive programming in a transparent manner (TFRP). Different Stores are supported by MobX, unlike certain libraries like Redux. [MobX](https://mobx.js.org/README.html) has a relatively low learning curve, so getting started with it is simple.

My name is Victory Tuduo and I am a software developer who loves building web applications, creating flexible UI designs, mentoring, and writing technical articles. You can find out more about me and my work [here](https://twitter.com/vhicktri) and [here](https://victorytuduo.vercel.app/).

## Subscribe for more CoderPad insights

## Trending Articles

Previous slide Next slide [Development

## What is Prompt Engineering?

Introducing AI tools such as ChatGPT and Bard helps increase the efficiency of tasks such as data generation, code generation and completion, text summarization, etc. How were these AI tools trained to answer almost every question you ask them? The answer, prompt engineering, is discussed in this blog post.

Read the post](https://coderpad.io/blog/development/what-is-prompt-engineering/) [Development

## A Guide To Using React’s useCallback() Hook

Are you looking to optimize your React applications? Have you heard of the useCallback hook? useCallback is a powerful React hook that helps you optimize your application by preventing unnecessary re-renders. In this post, we'll dive into React's useCallback() hook, define referential equality and callback functions and how to tie it all together.

Read the post](https://coderpad.io/blog/development/a-guide-to-using-reacts-usecallback-hook/) [Development

## MySQL vs. PostgreSQL: How Do They Compare?

A database is a convenient tool that allows users to access information, maintain records, and apply commonly used operations, such as insertion, modification, deletion, and data organization. Learn about MySQL vs PostgreSQL, their features, advantages, and disadvantages. Finally, check out which one is the best choice for you.

Read the post](https://coderpad.io/blog/development/mysql-vs-postgresql-how-do-they-compare/) [Development

## PostgreSQL LIKE Operator: A Detailed Guide

When using databases, searching for values that match a given pattern is a familiar necessity. Learn how you can retrieve entries with queries including a particular string using Postgres LIKE operator.

Read the post](https://coderpad.io/blog/development/postgresql-like-operator-a-detailed-guide/) [Development

## How To Use DataProvider In TestNG With Examples

When it comes to testing there are many tools and techniques available. In this post, we'll discuss how to use DataProvider with TestNG.

Read the post](https://coderpad.io/blog/development/how-to-use-dataprovider-in-testng-with-examples/) [Development

## How To Get Up And Running With Django Migrations: A Guide

Django migrations are a way of handling the application of changes to a database schema. By following the steps outlined in this guide, you can easily set up and use migrations in your Django projects.

Read the post](https://coderpad.io/blog/development/how-to-get-up-and-running-with-django-migrations-a-guide/) [Development

## Writing A Parameterized Test In JUnit With Examples

A JUnit parameterized test allows you to decouple data from structure, generating cleaner and more reliable tests. Learn more in this guide.

Read the post](https://coderpad.io/blog/development/writing-a-parameterized-test-in-junit-with-examples/) [Development

## How To Use Assert In JUnit With Examples

The JUnit Assert class is what you use to write unit testing assertions in JUnit. Learn more about it in this guide, full of examples.

Read the post](https://coderpad.io/blog/development/how-to-use-assert-in-junit-with-examples/) [Development

## A Simple Guide To TypeORM: What It Is And How To Use It

Considering current languages have object-oriented programming features, most database management systems are based on the relational model, with tables instead of objects. For these reasons, mapping relational objects is very important in development. In this article, you will learn what TypeORM, one of the main tools used today, is.

Read the post](https://coderpad.io/blog/development/a-simple-guide-to-typeorm-what-it-is-and-how-to-use-it/) [Development

## Using PreparedStatement in JDBC With Examples

In this post, we'll see why and how to work with JDBC and PreparedStatement. We will also learn along with examples using code.

Read the post](https://coderpad.io/blog/development/using-preparedstatement-in-jdbc-with-examples/) [Development

## React vs React Native: The Differences Explained

React and React Native are similar in that they both allow web developers to build applications based on the unique concept of components. But the two frameworks do this in radically different ways. In this post, we cover the key differences between react and react native frameworks, implementation, and which is an appropriate choice.

Read the post](https://coderpad.io/blog/development/react-vs-react-native-the-differences-explained/) [Development

## Logging in Django

The most challenging part of fixing a problem is identifying it. Unfortunately, this statement is exceptionally true when it comes to debugging. Learn how to use the power of logging into your Django applications to improve your debug process in this article.

Read the post](https://coderpad.io/blog/development/logging-in-django/)

## Hire with confidence.

See why engineering teams trust CoderPad to evaluate developers with realistic, AI-ready hiring workflows.

[Request a demo](https://coderpad.io/sales/)
