Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • Software and Tools
    • School Learning
    • Practice Coding Problems
  • Go Premium
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • jQuery
  • AngularJS
  • ReactJS
  • Next.js
  • React Native
  • NodeJS
  • Express.js
  • MongoDB
  • MERN Stack
  • PHP
  • WordPress
  • Bootstrap
  • Tailwind
  • CSS Frameworks
  • JS Frameworks
  • Web Development
Open In App
Next Article:
What is the use of React Context in React-Redux?
Next article icon

State Management in React: Context API vs. Redux vs. Recoil

Last Updated : 23 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

A fundamental idea in application development, State management is especially important for contemporary online and mobile apps, where dynamic, interactive user experiences necessitate frequent modifications to data and interface components. Fundamentally, it describes how an application maintains and monitors its "state"—the present state of variables, user inputs, retrieved data, and interface conditions—during the course of its lifetime.

This state changes as users engage with the application, and to preserve a consistent user experience, these changes must be mirrored throughout the user interface (UI). Effective state management entails managing the sharing, editing, and synchronization of data among many program components.

From minor, local state modifications (like monitoring a user's input in a form) to intricate global state modifications (like preserving a user's authentication status across several pages), this can take many forms. Applications that lack adequate state management may become challenging to maintain and debug, with poorly coordinated state updates leading to unpredictable behavior or inconsistent data.

These are the following subtopics that we are going to explore:

Table of Content

  • Why State Management is Important in React?
  • React Context API
  • Redux
  • Recoil
  • Difference between Context API , Redux and Recoil

Why State Management is Important in React?

As the complexity of the application increases, state management in React is essential for maintaining consistency and synchronization between data and the user interface (UI). Because the user interface (UI) in React is a reflection of the underlying state, to ensure a consistent user experience, any changes to the state must be appropriately reflected in the UI. Data inconsistencies or out-of-date user interface elements could result from components that don't update as intended due to improper state management.

Effective state management also avoids problems such as "prop drilling," which involves manually passing data through several levels of components, increasing the complexity and difficulty of maintaining the code. Multiple components frequently need to share or interact with the same data as applications get bigger. tools for state management, like Redux or React's Context API.

React Context API

The React Context API is a way to pass data through your component tree without manually passing props at every level. It allows you to store values that can be accessed by multiple components, avoiding "prop drilling."

Let’s create a Book List example where we manage a list of books and allow users to add new books to the list using the Context API.

1. Create the Context

We create a context using React.createContext() to store the global state and functions.

import React, { createContext, useState } from 'react';

// Create the BookContext

export const BookContext = createContext();

// BookProvider component to provide the context

export const BookProvider = ({ children }) => {
const [books, setBooks] = useState([
{ title: '1984', author: 'George Orwell' },
{ title: 'To Kill a Mockingbird', author: 'Harper Lee' }
]);

// Function to add a new book

const addBook = (title, author) => {
setBooks([...books, { title, author }]);
};

return (
<BookContext.Provider value={{ books, addBook }}>
{children}
</BookContext.Provider>
);
};

2. Consume the Context in Components

We will create two components:

  • BookList: To display the list of books.
  • AddBook: To add a new book to the list.

BookList Component: This component will consume the books array from the context using the useContext hook.

import React, { useContext } from 'react';
import { BookContext } from './BookContext';

const BookList = () => {
const { books } = useContext(BookContext); // Access books from context

return (
<div>
<h2>Book List</h2>
<ul>
{books.map((book, index) => (
<li key={index}>
<strong>{book.title}</strong> by {book.author}
</li>
))}
</ul>
</div>
);
};

export default BookList;

AddBook Component: This component will consume the addBook function from the context to add new books to the list.

import React, { useState, useContext } from 'react';
import { BookContext } from './BookContext';

const AddBook = () => {
const { addBook } = useContext(BookContext); // Access the addBook function
const [title, setTitle] = useState('');
const [author, setAuthor] = useState('');

const handleSubmit = (e) => {
e.preventDefault();
addBook(title, author); // Add the new book
setTitle(''); // Reset the input fields
setAuthor('');
};

return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Book title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="Author"
value={author}
onChange={(e) => setAuthor(e.target.value)}
/>
<button type="submit">Add Book</button>
</form>
);
};

export default AddBook;

3. Combine Components in the App

We will wrap the BookList and AddBook components inside the BookProvider to give them access to the context.


import React from 'react';
import { BookProvider } from './BookContext';
import BookList from './BookList';
import AddBook from './AddBook';

const App = () => {
return (
<BookProvider>
<h1>My Book List</h1>
<BookList />
<AddBook />
</BookProvider>
);
};

export default App;

This book list example showcases how to manage global state efficiently using the React Context API. It’s simple to implement and suitable for many use cases where the state doesn’t require complex logic or structure.

Redux

Redux is a state management library often used in larger React applications to manage global state in a predictable way. Redux provides a centralized store where all the state lives, and components can dispatch actions to update this state. It is commonly used in complex applications where state needs to be shared between many components.

Let’s use Redux to implement a Book List application. The goal is to manage a list of books, allow users to add new books, and display them using Redux for state management.

1. Defining Actions

Actions in Redux are plain JavaScript objects with a type field (to describe the action) and a payload field (to hold any data the action might need). For the Book List, we’ll define an action to add a book.

// actions.js

// Action type

export const ADD_BOOK = 'ADD_BOOK';

// Action creator to add a book

export const addBook = (title, author) => {
return {
type: ADD_BOOK,
payload: { title, author }
};
};

Here, addBook is an action creator that returns an action object with type: ADD_BOOK and the payload containing the new book’s title and author.

2. Creating a Reducer

Reducers in Redux are functions that take the current state and an action as arguments and return a new state based on the action.

// reducer.js

import { ADD_BOOK } from './actions';

// Initial state of the book list

const initialState = {
books: [
{ title: '1984', author: 'George Orwell' },
{ title: 'To Kill a Mockingbird', author: 'Harper Lee' }
]
};

// Reducer function to handle actions

const bookReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_BOOK:
return {
...state, // Keep the current state
books: [...state.books, action.payload] // Add new book to the list
};
default:
return state; // If action type doesn't match, return the current state
}
};

export default bookReducer;
  • The bookReducer checks the action.type. If it's ADD_BOOK, it adds the new book (found in action.payload) to the books array.
  • The reducer always returns a new state object instead of mutating the old state.

3. Creating the Store

The Redux store holds the global state of the application. We use createStore from Redux to create the store and pass it the reducer.

// store.js

import { createStore } from 'redux';
import bookReducer from './reducer';

// Create the Redux store with the reducer

const store = createStore(bookReducer);

export default store;

Here, the createStore function creates a Redux store using the bookReducer. This store will now manage the state of the books.

4. Connecting Redux to React

Now, we’ll create components to:

  • Display the book list.
  • Add new books to the list.

We’ll use react-redux to connect these components to the Redux store.

Installing React-Redux

First, install the necessary libraries:

npm install redux react-redux

BookList Component: This component will use useSelector to get the book list from the Redux store.

// BookList.js

import React from 'react';
import { useSelector } from 'react-redux';

const BookList = () => {
const books = useSelector((state) => state.books); // Access books from Redux store

return (
<div>
<h2>Book List</h2>
<ul>
{books.map((book, index) => (
<li key={index}>
<strong>{book.title}</strong> by {book.author}
</li>
))}
</ul>
</div>
);
};

export default BookList;

AddBook Component: This component will use useDispatch to dispatch the addBook action and add a new book to the Redux store.

// AddBook.js

import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { addBook } from './actions';

const AddBook = () => {
const [title, setTitle] = useState('');
const [author, setAuthor] = useState('');
const dispatch = useDispatch(); // Get dispatch function

const handleSubmit = (e) => {
e.preventDefault();
dispatch(addBook(title, author)); // Dispatch addBook action
setTitle(''); // Clear input fields
setAuthor('');
};

return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="Author"
value={author}
onChange={(e) => setAuthor(e.target.value)}
/>
<button type="submit">Add Book</button>
</form>
);
};

export default AddBook;

Main App Component: We will wrap our components with the Provider component from react-redux, passing the Redux store as a prop. This allows the components to access the store.

// App.js

import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import BookList from './BookList';
import AddBook from './AddBook';

const App = () => {
return (
<Provider store={store}>
<div>
<h1>My Book List</h1>
<BookList />
<AddBook />
</div>
</Provider>
);
};

export default App;

This example shows how Redux manages the state for a Book List application. It demonstrates the benefits of centralized state management, particularly in more complex applications where the state is shared across multiple components.

Recoil

Recoil is a state management library for React that is designed to be simple and scalable. Unlike Redux, Recoil allows you to manage global state but also provides tools to manage derived state and make state updates more efficient. It integrates seamlessly with React hooks like useState and useEffect.

In this example, we will implement a Book List using Recoil, where we can manage a list of books and add new books.

1. Installing Recoil

First, you need to install the Recoil package:

npm install recoil

2. Creating Atoms

Atoms in Recoil represent state that can be shared across components. For the Book List app, we’ll create an atom to store the list of books.

// atoms.js

import { atom } from 'recoil';

// Atom to store the list of books

export const bookListState = atom({
key: 'bookListState', // unique key to identify the atom
default: [
{ title: '1984', author: 'George Orwell' },
{ title: 'To Kill a Mockingbird', author: 'Harper Lee' }
], // initial state
});

Here, the bookListState atom stores the default list of books. It will be used in components to access and update the book list.

3. Creating Components

We’ll create two components:

  • BookList: Displays the list of books.
  • AddBook: Allows users to add a new book to the list.

BookList Component: This component will use useRecoilValue to access the current list of books from the bookListState atom.

// BookList.js

import React from 'react';
import { useRecoilValue } from 'recoil';
import { bookListState } from './atoms';

const BookList = () => {
const books = useRecoilValue(bookListState); // Access book list state

return (
<div>
<h2>Book List</h2>
<ul>
{books.map((book, index) => (
<li key={index}>
<strong>{book.title}</strong> by {book.author}
</li>
))}
</ul>
</div>
);
};

export default BookList;

In this component, useRecoilValue is used to access the bookListState atom, which holds the list of books. It renders each book in the list.

AddBook Component: This component will use useSetRecoilState to update the book list atom by adding new books.

// AddBook.js

import React, { useState } from 'react';
import { useSetRecoilState } from 'recoil';
import { bookListState } from './atoms';

const AddBook = () => {
const [title, setTitle] = useState('');
const [author, setAuthor] = useState('');
const setBooks = useSetRecoilState(bookListState); // Set the book list state

const handleSubmit = (e) => {
e.preventDefault();
setBooks((prevBooks) => [
...prevBooks,
{ title, author }
]); // Add new book to the list
setTitle(''); // Clear input fields
setAuthor('');
};

return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
placeholder="Author"
value={author}
onChange={(e) => setAuthor(e.target.value)}
/>
<button type="submit">Add Book</button>
</form>
);
};

export default AddBook;

In this component, useSetRecoilState is used to update the bookListState atom. When the form is submitted, the new book is added to the list.

4. Wrapping the App with RecoilRoot

To use Recoil in your app, you need to wrap your entire app with the RecoilRoot component. This component makes the Recoil state available to all the components in your app.

// App.js

import React from 'react';
import { RecoilRoot } from 'recoil';
import BookList from './BookList';
import AddBook from './AddBook';

const App = () => {
return (
<RecoilRoot>
<div>
<h1>My Book List</h1>
<BookList />
<AddBook />
</div>
</RecoilRoot>
);
};

export default App;

This book list example demonstrates how Recoil can be used for state management in React. Recoil's simplicity and efficiency make it an excellent alternative to Redux, especially for React applications that don’t require as much boilerplate or have complex state logic.

Difference between Context API , Redux and Recoil

Feature

Context API

Redux

Recoil

Core Concept

Context provides a way to pass data deeply through the component tree without manually passing props down at every level.

Redux manages global state via a centralized store with actions, reducers, and strict rules for state mutations.

Recoil provides shared state across components using atoms (state units) and selectors (derived state). Efficient and React-centric.

Use Case

Ideal for small to medium apps where a few global states are needed (e.g., theme, user session).

Ideal for large applications with complex state logic that requires a predictable state flow.

Suitable for both small and large apps, particularly where you need shared or derived state, with minimal boilerplate.

Complexity

Easy to use for simple use cases but becomes complicated with deeply nested state or many providers.

Complex due to the setup of actions, reducers, middleware, and store, especially for async operations

Very simple to set up, even for large applications. Atoms and selectors make state management straightforward.

Boilerplate Code

Very little boilerplate. Just set up Context and Provider.

A lot of boilerplate (actions, reducers, store configuration, action types).

Minimal boilerplate. Only atoms and selectors, similar to useState and useEffect hooks.

Middleware and Side Effects

Lacks built-in middleware. You’ll need to manage side effects (e.g., async operations) using hooks (useEffect).

Supports middleware like redux-thunk or redux-saga to handle side effects and async logic.

Built-in support for handling async logic using Recoil’s selectors, which makes it easy to handle derived or asynchronous state.


Next Article
What is the use of React Context in React-Redux?

G

garvitshyw97
Improve
Article Tags :
  • GBlog
  • Web Technologies
  • Web-Tech Blogs

Similar Reads

    State Management in React – Hooks, Context API and Redux
    State management is a critical concept when working with React. React components can hold local state, but as applications grow, managing state across multiple components can become complex. To help manage this complexity, React provides several tools: Hooks, Context API, and Redux. Here are some fe
    6 min read
    Using the React Context API for Efficient State Management
    The React Context API is a robust feature announced in React 16.3. It offers a way to share data within components without passing props directly at all stages. This is specifically useful for global data that many components seek to access, like user authentication, theme, or language settings. Rat
    5 min read
    Introduction to Recoil For State Management in React
    State Management is a core aspect of React development, especially as applications grow in size and complexity. While there are many libraries available to handle state, recoil has emerged as the fresh, modern approach that simplifies state management without the bloat of more complex systems like R
    6 min read
    What is the use of React Context in React-Redux?
    React Context is a feature that React provides us to manage states required in multiple components. Redux is also a state management library and solves the same problem that React Context does but in a different way. In this article, we will see in detail what is react context, why and how to use it
    5 min read
    Mastering State Management in ReactJS: A Beginner's Guide to the Context API
    State Management in React.js is an essential topic as the whole of React counters & controllers work through their states. State is the initial value of the component, or the current value & using state management we can change the value by some specific functionalities using react.js. One s
    10 min read
    State management using Redux in Flutter
    State management is a crucial aspect of building dynamic and responsive applications. While building applications, we sometimes need to maintain a state between multiple screens. Here comes the part of State Management. There are different state management techniques in Flutter like GetX, Provider,
    6 min read
`; $(commentSectionTemplate).insertBefore(".article--recommended"); } loadComments(); }); }); function loadComments() { if ($("iframe[id*='discuss-iframe']").length top_of_element && top_of_screen articleRecommendedTop && top_of_screen articleRecommendedBottom)) { if (!isfollowingApiCall) { isfollowingApiCall = true; setTimeout(function(){ if (loginData && loginData.isLoggedIn) { if (loginData.userName !== $('#followAuthor').val()) { is_following(); } else { $('.profileCard-profile-picture').css('background-color', '#E7E7E7'); } } else { $('.follow-btn').removeClass('hideIt'); } }, 3000); } } }); } $(".accordion-header").click(function() { var arrowIcon = $(this).find('.bottom-arrow-icon'); arrowIcon.toggleClass('rotate180'); }); }); window.isReportArticle = false; function report_article(){ if (!loginData || !loginData.isLoggedIn) { const loginModalButton = $('.login-modal-btn') if (loginModalButton.length) { loginModalButton.click(); } return; } if(!window.isReportArticle){ //to add loader $('.report-loader').addClass('spinner'); jQuery('#report_modal_content').load(gfgSiteUrl+'wp-content/themes/iconic-one/report-modal.php', { PRACTICE_API_URL: practiceAPIURL, PRACTICE_URL:practiceURL },function(responseTxt, statusTxt, xhr){ if(statusTxt == "error"){ alert("Error: " + xhr.status + ": " + xhr.statusText); } }); }else{ window.scrollTo({ top: 0, behavior: 'smooth' }); $("#report_modal_content").show(); } } function closeShareModal() { const shareOption = document.querySelector('[data-gfg-action="share-article"]'); shareOption.classList.remove("hover_share_menu"); let shareModal = document.querySelector(".hover__share-modal-container"); shareModal && shareModal.remove(); } function openShareModal() { closeShareModal(); // Remove existing modal if any let shareModal = document.querySelector(".three_dot_dropdown_share"); shareModal.appendChild(Object.assign(document.createElement("div"), { className: "hover__share-modal-container" })); document.querySelector(".hover__share-modal-container").append( Object.assign(document.createElement('div'), { className: "share__modal" }), ); document.querySelector(".share__modal").append(Object.assign(document.createElement('h1'), { className: "share__modal-heading" }, { textContent: "Share to" })); const socialOptions = ["LinkedIn", "WhatsApp","Twitter", "Copy Link"]; socialOptions.forEach((socialOption) => { const socialContainer = Object.assign(document.createElement('div'), { className: "social__container" }); const icon = Object.assign(document.createElement("div"), { className: `share__icon share__${socialOption.split(" ").join("")}-icon` }); const socialText = Object.assign(document.createElement("span"), { className: "share__option-text" }, { textContent: `${socialOption}` }); const shareLink = (socialOption === "Copy Link") ? Object.assign(document.createElement('div'), { role: "button", className: "link-container CopyLink" }) : Object.assign(document.createElement('a'), { className: "link-container" }); if (socialOption === "LinkedIn") { shareLink.setAttribute('href', `https://www.linkedin.com/sharing/share-offsite/?url=${window.location.href}`); shareLink.setAttribute('target', '_blank'); } if (socialOption === "WhatsApp") { shareLink.setAttribute('href', `https://api.whatsapp.com/send?text=${window.location.href}`); shareLink.setAttribute('target', "_blank"); } if (socialOption === "Twitter") { shareLink.setAttribute('href', `https://twitter.com/intent/tweet?url=${window.location.href}`); shareLink.setAttribute('target', "_blank"); } shareLink.append(icon, socialText); socialContainer.append(shareLink); document.querySelector(".share__modal").appendChild(socialContainer); //adding copy url functionality if(socialOption === "Copy Link") { shareLink.addEventListener("click", function() { var tempInput = document.createElement("input"); tempInput.value = window.location.href; document.body.appendChild(tempInput); tempInput.select(); tempInput.setSelectionRange(0, 99999); // For mobile devices document.execCommand('copy'); document.body.removeChild(tempInput); this.querySelector(".share__option-text").textContent = "Copied" }) } }); // document.querySelector(".hover__share-modal-container").addEventListener("mouseover", () => document.querySelector('[data-gfg-action="share-article"]').classList.add("hover_share_menu")); } function toggleLikeElementVisibility(selector, show) { document.querySelector(`.${selector}`).style.display = show ? "block" : "none"; } function closeKebabMenu(){ document.getElementById("myDropdown").classList.toggle("show"); }
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences