Codementor Events

State management with React Context + Hooks

Published Mar 03, 2020Last updated Sep 08, 2021
State management with React Context + Hooks

There are many way to handle global state managements like Redux, MobX, Jumpsuit etc. If you have already used redux then you remember action, store, reducer and some functions like connect(), useStateToProps, useDispatchToProps are able to access the state.

But now in react 16.8 and above, you don't need to use third party library redux. React provides its own hooks and apis like useContext.

Why react context ?

Imagine you have 5 components and you want to share the state from one component to other but you can only share the state from parent to child component using props and child to parent using ref or callback.
noname.png
In the above figure, you can share the state from component 1 to component 4, component 2 to component 5 and component 3 to component 5 and vice versa. But if you want to share the data from component 1 to component 2 or component 3 then you can't do.

**This is where Context comes to the rescue. **

What is react context ?

The React Context API allows you to easily access data at different levels of the component tree. It creates a parent most component which is Context and it store all the data which is accessible from all the components of the project.
noname.png
In the above figure, store stores all the states of all the components and all components will access all the states of any component.

How does context works ?

1. Creating a counter context and adding a new state management

import React, { useReducer } from "react";
let reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { ...state, count: state.count + 1 };
    case "DECREMENT":
      return { ...state, count: state.count - 1 };
    default:
      return;
  }
};
const initialState = { count: 0 }
const CounterContext = React.createContext(initialState);
function CounterProvider(props) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
   <CounterContext.Provider value={{ state, dispatch }}>
      {props.children}
    </CounterContext.Provider>
  );
}
export { CounterContext, CounterProvider };

If you’ve worked with Redux before, this is probably going to look familiar.

we did a couple of things here

  1. create a CounterContext that takes {count: 0} as the initialState and we export the Providers and Context.
  2. Create a reducer that takes a state and action.
  3. Use array destructuring to get the state and dispatch object from useReducer.
  4. Pass the value {state, dispatch} in CounterContext.Provider so we can pass the shared state and dispatch to all the components.

2. Get the shared state and dispatch objects in the components

function Counter() {
 const { state, dispatch } = useContext(CounterContext);
 return (
    <div>
      <h5>Count: {state.count}</h5>
      <button onClick={() => dispatch({ type: "INCREMENT" })}>
        +
      </button>
    <button onClick={() => dispatch({ type: "DECREMENT" })}>
        -
     </button>
    </div>
  );
}

Since we passed the state and dispatch objects as the value of the CounterContext.Provider. So it returns a object which have state and dispatch function. We can use the object using useContext(CounterContext) and it returns like

{
  state: { count: 0 },
    dispatch: fn()
}

If we click on + button then it dispatch and pass the arguments { type: "INCREMENT" } then the reducer function should call where switch case compare the type and it returns { ...state, count: state.count + 1 } that means the count will increase by 1 and useContext() pull the state from context.

Reference: https://reactjs.org/docs/hooks-reference.html#usecontext
We are a development team from a company which is Software Development Company in Lucknow

Discover and read more posts from Mohit Prakash
get started