mohan's blog

mohan's blog

useContext() Simplified

In this blog post, we are going to explore how to use the useContext() hook and why should we use it. But let's first understand the Why before the How.

The why is more important than how

Why use useContext()

useContext() is basically used for providing data throughout the application that can be considered global, which can be accessed by any component in the tree hierarchy. Before useContext(), developers used to use a technique known as "Props Drilling", which basically means "passing the same data throughout the tree hierarchy even though most of the components does not need/use it."

This can be better understood with the help of an example, for suppose, let's consider a situation where component A need to pass data to component C, which is a child component of component B. First we pass the data over to component B and then to component C, but component B does not require the data. To solve this, the useContext() hook was developed.

How to use the useContext() hook

The three main parts of using the useContext() hook are:

  1. Creating the context,
  2. Providing the context to the Provider Component, and
  3. Using the context value, which is now the global state.

Let's understand this better with the use of an example.

1. Creating Context

Let's understand what the code is trying to convey. First we have imported the useContext() hook from react and assigning it to the variable named DataContext.

/* DataContext.js */
import { createContext, useState } from "react";

export const DataContext = createContext();

export default function DataProvider({ children }) {
  const [initialState, setInitialState] = useState({ count: 0 });

  const incrementCount = () => {
    setInitialState((state) => ({ ...state, count: state.count + 1 }));
  };

  return (
    <DataContext.Provider value={{ initialState, incrementCount }}>
      {children}
    </DataContext.Provider>
  );
}

2. Providing state to the entire application

Then we have simplified version of Provider component. Whichever component the Provider component wraps around will become its child component.Since we need our state to be global i.e., available throughtout the application, we will be wrapping it around our App component, thereby providing global state to the entire application.

Then we have the value attribute, which would be the needed state by the application. The value attribute takes string/object/array/number etc., But for obvious reasons, we will be sending an object containing initialState & incrementCount.This initialState & incrementCount will available throughout the application.

/* index.js */
import React from "react";
import App from "./App";
import DataProvider from "./DataContext";

ReactDOM.render(
  <CartProvider>
    <App />
  </CartProvider>
,document.getElementById('root')
);

3. Using the Context value

/* App.js */
import React from "react";
import Counter from "./Counter";

export default function App() {
  return (
  <div className="App">
    <Counter />
  </div>
  )
}
/* Counter.js */
import React, { useContext } from "react";
import { DataContext } from "./context/DataContext";

export default function Counter() {
  const state = useContext(DataContext);
  const { initialState, incrementCount } = state;

  return (
    <div className="Counter">
      <p>{initialState.count}</p>
      <button onClick={ () => incrementCount() }> + </button>
    </div>
  );
}

Coming to the explaination, we are importing the useContext() hook from react and providing it with the context object. Then we are extracting the initialState & incrementCount throught object destructing. Finally, then we are rendering the count on the screen and a button, which on clicked, increments the count value.

This is the why and how of react's useContext() hook.

 
Share this