React useState Vs. Context API: When to Use Them
Tags: react, webdev
Published: 2023-06-08 13:18:49

---
title: React useState Vs. Context API: When to Use Them
published: true
date: 2023-06-08 12:01:30 UTC
tags: react, webdev
canonical_url: https://www.syncfusion.com/blogs/post/react-usestate-vs-context-api.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ucf0jskdajmji0z9xvex.png
---
[React](https://en.wikipedia.org/wiki/React_(software) "Wikipedia page for React") has improved its state management abilities throughout its journey. With the 16.3 upgrades, the React team introduced Context API to quickly share a state across the entire application or a portion of it. On the other hand, [React Hooks](https://legacy.reactjs.org/docs/hooks-intro.html "React Hooks documentation") came as a new addition to React with version 16.8. React Context API and React useState Hook manage the state in a React application but differ in their use cases and implementations.

So, in this article, I will compare Context API and useState Hook. For better understanding, I have provided various use cases for each.

## What is Context API?

React Context API is a feature in React that allows data to be passed down through a component tree without having to manually pass props down through every level of the tree. It provides a way to share data between components not directly related to each other in the component hierarchy.

There are situations when multiple components at different nesting levels in a tree need access to the same data. Context lets you **broadcast** such data across components in a tree, whether at different nested levels or the same nested level. Additionally, it permits these components to modify the data as required.

Although open-source libraries like Redux are helpful when developers want to manage and centralize application states, many developers find Redux somewhat complicated to learn and operate. Alternatively, Context API helps you manage the global states in your React application easily.

## How does Context API work?

To use React Context API, you need to create a **context** object using the **createContext()** method. This **context** object provides two components: Provider and Consumer. The Provider component allows you to wrap the entire component tree with a context object and pass down data as a prop to all the components inside it. The created context object holds the latest value of the state. The context object must be the parent component for all components that want to use the state value. The Consumer component allows you to access the data passed down by the Provider component.

Here’s an example of how to use React Context API.

```js
import React, { createContext, useState } from "react";
const ThemeContext = createContext();
function App() {
  const [theme, setTheme] = useState("light");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <MainPage />
    </ThemeContext.Provider>
  );
}
function MainPage() {
  return (
    <div>
      <Header />
      <Content />
    </div>
  );
}
function Header() {
  return (
    <header>
      <nav>
        <ThemeToggler />
      </nav>
    </header>
  );
}
function ThemeToggler() {
  const { theme, setTheme } = useContext(ThemeContext);
  return (
    <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
      Toggle theme
    </button>
  );
}
```

In the previous example, I imported **createContext** from the React module. I defined and initialized the **ThemeContext** object using the **createContext** function in the following line. The best practice is creating a separate folder outside the components directory to contain all the contexts.

The **theme** state and **setTheme** state update functions are passed as the context’s values, and the entire application is wrapped in a **ThemeContext.Provider** component. Using the **useContext** Hook pass and the **ThemeContext** object as the argument, any component within the component tree can access the theme **state** and the **setTheme** function.

### Provide a state value to Context API

When creating the context object, we initialize its current state value with **defaultValue**. The created context object reads values from the closest matching Provider above it in the component tree and stores it as the current context value. See the code snippet below for a better understanding.

```js
import React, { useState, createContext } from 'react';
export const FruitContext = createContext();
export const FruitProvider = (props) => {
  const fruitList = [
    {
      name: 'Banana',
      price: '2 USD'
    }, 
    {
      name: 'Apple',
      price: '2.50 USD'
    }, 
    {
      name: 'Mango',
      price: '5 USD'
    }
  ]
  
  return(
    <FruitContext.Provider value = { fruitList } >
      {props.children}
    </FruitContext.Provider>
  );
}
```

In the example, **fruitList** is a list of fruit objects we have created. All children wrapped from the FruitContext Context Provider can receive the **fruitList** value.

### Subscribe state values from Context API

Context API has two different ways to subscribe to the state values.

#### Option 01

The first way to subscribe to context changes is to use the **Context.Consumer** property in a function component. The consumer requires a function as a child to receive the current context value.

```js
import { FruitContext } from '../Contexts/FruitContext';
function Fruits() {
  return (
    <FruitContext.Consumer>
      {value => <><h1>{value[0].name}</h1> <h3>{value[0].price}</h3></> }
    </FruitContext.Consumer>
  )
}
```

On top of the above code, we have imported the created context API. The attributes inside **FruitContext.Consumer** can consume the latest value of the state. The **value** contains the list of fruits we have passed. The returning output is below. ![Context.Consumer property output](https://www.syncfusion.com/blogs/wp-content/uploads/2023/06/Context.Consumer-property-returning-output-1.png)

#### Option 02

With the advent of React Hooks, there is another way to get context values. The nested components can now consume Context with the **useContext** Hook.

```js
import React, { useContext } from 'react';
import { FruitContext } from '../Contexts/FruitContext';
const FruitBacket = () => {
  const fruitList= useContext(FruitContext);
  
  return (
    <div>
      {fruitList.map(fruit => (
        <div>
          <h1>Name: {fruit.name}</h1>
          <h3>Price: {fruit.price}</h3>
        </div>
      ))}
    </div>
  );
};
```

In the nested component ( **FruitBacket** ), import the **useContext** Hook and the **Context** object we have created. Inside a functional component, **useContext** can be called like **useState** to get the state values. The above code snippets output the following. ![useContext Hook Output](https://www.syncfusion.com/blogs/wp-content/uploads/2023/06/useContext-Hook-Output.png)

## When to use Context API

As we discussed, avoiding prop drilling (passing data to the child or nested components) is the best achievement of Context API. It will keep your code cleaner and easy to work.

Here are some scenarios where using React Context API can be beneficial:

- **Global data:** If you have data that needs to be accessed by multiple components throughout your application, such as the current user object, theme, or localization settings, you can use the React Context API to share this data across your components.
- **Avoiding prop drilling:** If you pass props down multiple levels of the component tree, especially when the intermediate components do not directly use the props, it might be a good idea to use React Context API to avoid prop drilling and simplify your component code.
- **Large-scale applications:** If you’re building a large-scale application with many components and complex data flows, React Context API can help you manage your state and data more efficiently and make your code more maintainable.
- **Cross-cutting concerns:** If you have cross-cutting concerns in your application, such as error handling or authentication, that need to be applied across multiple components, using React Context API can make managing these concerns easier and keeps your code organized.

## What is useState Hook?

The **useState** function helps manage state(local state) variables within a React functional component. You are responsible for the initial value of the state, and the **useState** function returns the current value along with a method to modify it.

## How does useState work?

### Declaring useState

On the top of the file, import **useState** Hook from React. In functional components, replace **this.state** of the class components with useState. Then you can directly call **useState** inside the functional component.

```js
import React, { useState } from 'react';
const AddFruitToBucket = () => {
  const [name, setName] = useState('');
  const [price, setPrice] = useState(0);
  return (
     {/* return code */}
  );
};
export default AddFruitToBucket;
```

The previous code created the current state and a method to change the current state for name and price variables.

### Calling useState

It’s easy to get the values of states defined using **useState**. However, if you want to call them inside HTML tags, you must wrap them in curly braces.

```js
const Fruit = () => {
  const [name, setName] = useState('');
  const [price, setPrice] = useState(0);
  
  return (
    <div>
      <h1>Name: {name}</h1>
      <h3>Price: {price}</h3>
    </div>
  );
};
```

### Modify a state value using useState

I have mentioned that **useState** returns a pair of values when it declares a state. The second variable is a function to update the current value of the state. Using that, you can easily modify the state value.

```js
function Example() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

```

The previous example demonstrates a simple example of changing the value of the count state using the **useState** Hook.

## When to use UseState

Present-day developers prefer using React functional components since they’re simpler than class components. In addition, the **useState** Hook allows you to add stateful behavior to functional components without the need for class components. Here are some scenarios where using React **useState** Hook can be beneficial:

- **Form inputs:** If your component has form inputs, use the **useState** Hook to manage their state. This allows you to keep track of user input and update the UI accordingly.
- **Conditional rendering:** If you have components that need to change their state based on user actions or some other condition, use the **useState** Hook to manage the component’s state and re-render the component when the state changes.
- **UI components:** If UI components need to change their state based on user interaction, such as dropdown menus, tabs, or accordions, use the **useState** Hook to manage the component’s state and update the UI accordingly.
- Toggling: If you have components that need to toggle between two or more states, such as a modal or a tooltip, use the useState hook to manage the component’s state and toggle between the different states.

We can create a toggle flag in a functional component using **useState** Hook. The following code explains how you can turn a toggle on or off using **useState** Hook.

```js
import React, { useState } from 'react'
const FruitBucket = () => {
  const [toggle, setToggle] = useState(false)
  return(
    <><button onClick={() => setToggle(!toggle)}>Add to Cart!</button></>
  )
}

```

You may utilize a state to store the fetch() response from the API when using APIs and the spinner’s state to show if data is being fetched. The following code is an example of that. **isLoading** is used to indicate the data state. Once the data is fully retrieved, **“Data loaded!”** will show.

```js
const ShowPlanets = props => {
  const [isLoading, setIsLoading] = useState(false);
  
  const loadPlanets = async () => {
    setIsLoading(true);
  
    const response = await fetch('https://swapi.dev/api/planets');
    const planets = await response.json();
    console.log(JSON.stringify(planets, null, "\t"));
  
    setIsLoading(false);
  };
  
  return (
    <>
     {isLoading? (
      <div><p>Data is loading...</p></div>
     ) : (
      <div><p>Data loaded!</p></div>
     )}
    </>
  );
};
```
## Conclusion

Throughout this article, I have discussed the main differences between React useState Hook and React Context API. React Context API shares data across components, while useState Hook manages the state within a single component.

Also, I have shown you the best way to use these React features in different scenarios. I hope this article guides you to get the most out of useState Hook and Context API.

Thank you for reading!

The [Syncfusion Essential Studio for React](https://www.syncfusion.com/react-ui-components "Syncfusion React UI Components") suite offers over 70 high-performance, lightweight, modular, and responsive UI components in a single package. It’s the only suite you’ll need to construct a complete app.

If you have questions, contact us through our [support forum](https://www.syncfusion.com/forums "Syncfusion Support Forum"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). We are always happy to assist you!

## Related blogs

- [Launch a React App in a Docker Environment](https://www.syncfusion.com/blogs/post/launch-react-app-in-docker.aspx "Blog: Launch a React App in a Docker Environment")
- [Empowering Mobile Users with Syncfusion React Data Grid’s Adaptive UI Layout](https://www.syncfusion.com/blogs/post/empowering-mobile-users-with-syncfusion-react-data-grids-adaptive-ui-layout.aspx "Blog: Empowering Mobile Users with Syncfusion React Data Grid’s Adaptive UI Layout")
- [Integrating Google Calendar Events with Syncfusion React Scheduler [Webinar Show Notes]](https://www.syncfusion.com/blogs/post/integrate-google-calendar-with-react-scheduler.aspx "Blog: Integrating Google Calendar Events with Syncfusion React Scheduler [Webinar Show Notes]")
- [Creating a CRUD-Enabled Scheduling App with Syncfusion React Scheduler, Node.js, and PostgreSQL](https://www.syncfusion.com/blogs/post/crud-react-scheduler-node-js-postgresql.aspx "Blog: Creating a CRUD-Enabled Scheduling App with Syncfusion React Scheduler, Node.js, and PostgreSQL")