Backbencher.dev

useContext() React Hook

Last updated on 17 Apr, 2022

Context makes it easy to pass data from a component to any of its child components. The child component can be of any level.

Passing Data Without Props

Here we have four components. It is named as L1, L2, L3, L4 to show the level of component in which it is used.

export default function L1() {
  return (
    <div>
      <h4>Level 1</h4>
      <L2 />
    </div>
  );
}

function L2() {
  return (
    <div>
      <h4>Level 2</h4>
      <L3 />
    </div>
  );
}

function L3() {
  return (
    <div>
      <h4>Level 3</h4>
      <L4 />
    </div>
  );
}

function L4() {
  return (
    <div>
      <h4>Level 4</h4>
    </div>
  );
}

We need to now pass some data from L1 to L4. How to do it? The only way is like water flowing down in steps. The data needs to be passed from L1 to L2 through props, then from L2 to L3 and finally, L3 to L4. Here is how it looks like:

export default function L1() {
  const name = "Joby";

  return (
    <div>
      <h4>Level 1</h4>
      <L2 name={name} />
    </div>
  );
}

function L2(props) {
  return (
    <div>
      <h4>Level 2</h4>
      <L3 name={props.name} />
    </div>
  );
}

function L3(props) {
  return (
    <div>
      <h4>Level 3</h4>
      <L4 name={props.name} />
    </div>
  );
}

function L4(props) {
  return (
    <div>
      <h4>Level 4</h4>
      <h3>Name is {props.name}</h3>
    </div>
  );
}

Above code produces below output:

Pass data through props

You can play with this code online at CodeSandbox.

Passing Data Using Context

Context acts like a global space. Once we create and connect a context to a component, the component and all its children have access to the context to fetch the data. It will be more clear with an example.

Create Context

First step is to create a context object. For that, import createContext from React.

import { createContext } from "react";

Next, we create a context object.

const NameContext = createContext("John");

Here, "John" is the default value of the context. We can override the value when using the context object.

Provide Context

We need to now provide the context to the L1 component. For that, wrap the L1 component inside NameContext.provider. Also, we can pass a value attribute. This value is then available to all child components.

export default function L1() {
  const name = "Joby";

  return (
    <NameContext.Provider value={name}>
      <div>
        <h4>Level 1</h4>
        <L2 name={name} />
      </div>
    </NameContext.Provider>
  );
}

As we can see above, we are passing a string "Joby" as value. This new value override the default "John" value.

Read Context Value

In the earlier section, we provided the value in L1 component. Next, we are trying to take the value in L4 component. For that, we can use useContext() hook.

function L4() {
  const name = useContext(NameContext);
  return (
    <div>
      <h4>Level 4</h4>
      <h3>Name is {name}</h3>
    </div>
  );
}

useContext() accepts a context object and returns the value it stores. This is how useContext() shares data across components.

useContext() Usage

If in our application, we need some data to be available globally, it is good to use Context. One application can be site theme. Based on Light or Dark theme, all the components needs to update their styles.

Context vs Redux

Latest Redux internally uses Context API. It is suggested to use either Redux or Context. Using both at the same time is not suggested.

--- ○ ---
Joby Joseph
Web Architect