The Context API and useReducer Hook

Posted By : Mohit Kumar | 19-Feb-2024

ReactJS Web Application Development

Loading...

In the world of React development, managing state efficiently and passing data across components can be a challenging task, especially in larger applications with complex component trees. Thankfully, React provides powerful tools to address these challenges, namely the Context API and the useReducer hook.

Understanding the Context API

Data can be sent through the component tree of React without the need to manually send props down at each level thanks to the Context API. It allows you to create a global state that is available to any component inside a specified scope, which is typically referred to as a "provider."

Creating a Context


You can use React's createContext method to create a context.

import { createContext } from 'react';

const MyContext = createContext();

Providing and Consuming Context


After creating a context, you can use a Provider component to supply its value and the useContext hook to consume it.

// App.js
import React from 'react';
import { MyContext } from './MyContext';
import ChildComponent from './ChildComponent';

function App() {
  const value = 'Hello from Context!';
  
  return (
    <MyContext.Provider value={value}>
      <ChildComponent />
    </MyContext.Provider>
  );
}

export default App;

Also, Read Advanced Search Using Criteria API

// ChildComponent.js
import React, { useContext } from 'react';
import { MyContext } from './MyContext';

function ChildComponent() {
  const value = useContext(MyContext);
  
  return <div>{value}</div>;
}

export default ChildComponent;

Introducing the useReducer Hook

The anothereffective tool that React offers for handling intricate state logic in functional components is the useReducer hook. It is a substitute for useState that works better for managing state objects that have several sub-values or in situations where one state depends on another.

The current state and a dispatch function to update the state are returned by the useReducer hook in exchange for a reducer function and a starting state.

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  
  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

export default Counter;

Combining Context API with useReducer

Combining React's useReducer hook and Context API to manage complex state in a global context is one of their most useful utilize cases. Without using prop drilling, this method enables you to concentrate your state management logic and distribute it throughout your application.

// StateContext.js
import React, { createContext, useReducer } from 'react';

const initialState = {
  count: 0
};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'decrement':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
}

export const StateContext = createContext();

export const StateProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <StateContext.Provider value={{ state, dispatch }}>
      {children}
    </StateContext.Provider>
  );
};

Also, Read An Overview of REST and RESTful APIs


// App.js
import React from 'react';
import { StateProvider } from './StateContext';
import Counter from './Counter';

function App() {
  return (
    <StateProvider>
      <Counter />
    </StateProvider>
  );
}

export default App;

In this example, we've used the useReducer hook to generate a global state, and the Context API has allowed us to make it available to the entire application. As a result, any StateProvider component can access the global state and send actions to update it.