Understanding the context of React's useContext Hook

Understanding the context of React's useContext Hook

ยท

3 min read

Need for useContext

Development in React got easier after the introduction Hooks in React v16. 8.0. Among the gems like useState and useEffect is the useContext Hook.

Before we go further, lets consider a scenario where you have nested react components similar to shown below:

import { StrictMode } from "react";
import ReactDOM from "react-dom";

export default function GrandFather () {
  const WISDOM = "WISDOM";
  return (
    <>
      <div>I am GrandFather - and I have {WISDOM}</div>;
      <Son knowledge={WISDOM}></Son>
    </>
  );
}

export function Son({ knowledge }) {
  return (
    <div>
      <div>Lets's Play {knowledge}</div>
      <GrandSon knowledge={knowledge} />
    </div>
  );
}

export function GrandSon({ knowledge }) {
  return <>Goo Goo... Gaa Gaa... {knowledge}</>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <GrandFather />
  </StrictMode>,
  rootElement
);

For the GrandSon component to have GrandFather's - Wisdom, it must be passed through Son.

Here, we only had three components where we can track the source of props, but consider scenarios when there are N-number of components where the props are being passed down the hierarchy, tracking the source of state will be much harder - this is nothing but prop drilling.

1-prop-drilling.jpg

And the solution to the Prop Drilling Problem is, to store the state in a way which makes the state globally accessible to all components - without the need of passing props, which React's Context API does hand-in-hand with useContext Hook.

2-context-magic.jpg

Consuming a State Globally with useContext is a 5 step process

Step 1: Create - a Global Context with React's context api

// src/context/context.jsx
import React from "react";

const GlobalContext = React.createContext();

step 2: Add - a Global Context Provider This will store and provide the global state to all children of this component.

// src/context.jsx
export function GlobalProvider({ children }) {
const WISDOM = 'WISDOM'
  return (
    <GlobalContext.Provider value={WISDOM }>
      {children}
    </GlobalContext.Provider>
  );
}

step 3: Wrap - the Root App with the GlobalProvider

// index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { GlobalProvider } from './context/context.js'

/**
 * remaining code...
 */

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <GlobalProvider >
      <FatherApp />
    </GlobalProvider >
  </StrictMode>,
  rootElement
);

step 4: Make a Custom Hook for convience

// src/context/context.jsx

export function useGlobalState() {
  return React.useContext(GlobalContext) 
}

step 5: Consume - the state in desired component via custom hook

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { GlobalProvider } from './context/context.js'

export default function GrandFather () {
  // the state is at global level
  const { WISDOM } = useGlobalState()
  return (
    <>
      <div>I am GrandFather - and I have {WISDOM}</div>;
      <Son knowledge={WISDOM}></Son>
    </>
  );
}

export function Son() {
  return (
    <div>
      <div>Lets's Play </div>
      <GrandSon />
    </div>
  );
}

export function GrandSon({ knowledge }) {
  const { WISDOM } = useGlobalState()
  return <>Goo Goo... Gaa Gaa... {WISDOM }</>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <GlobalProvider >
      <FatherApp />
    </GlobalProvider >
  </StrictMode>,
  rootElement
);

Things to keep in mind

The current state value of a component is determined by the value prop of the nearest <Context.Provider> above the calling component in the tree.

When the nearest <Context.Provider> above the component updates, this Hook will trigger a re-render with the latest context value passed to that Context provider.

A component calling useContext will always re-render when the context value changes.

Cons

Though useContext solves the problem of prop drilling but multiple nested contexts can create a huge context tree as shown below.

react context tree.jpg

Here are some links for reference with context,

This is my first blog ๐Ÿ˜Š but won't be the last one ๐Ÿ˜œ. Thanks for Reading โค๏ธ