React Context

This is effectively another way of storing data.

The problem

Let's say you have a state hook that you define in App, it's used in Child Component 1, so you pass it down to Child Component 1. It's also used in Grandchild Component 2, so you have to pass it down to Child Component 2, which doesn't use it and just passes it down to Grandchild Component 2.

Passing props down through components that don't use it in order to get to ones that do is called prop drilling. In the same way you'd drill through the earth to get to the oil, you drill through components to get the final one.

Context to the rescue!

Context keeps the data at a global level, so any component can access it, no matter where it is. So in our example, the data would be available globally, which Child Component 1 and Grandchild Component 2 can access. App and Child Component 2 don't have to have any idea about it at all.

How to use it

Basically you create a context, then tell components to use it. Here's an example:

CountContext:

import { createContext } from 'react';
export const CountContext = createContext();

This is simple - all you have to do is to create it. That's it.

App:

import { useState } from 'react';
import CountContext from './contexts/CountContext';

const App = () => {
  const [count, setCount] = useState();

  return (
    <CountContext.Provider value={{ count, setCount }}>
      <ChildComponent />
    </ CountContext.Provider>

  )
}

We're still setting our hooks at the highest point we need them, as usual. The difference here is that instead of sending the hook to the ChildComponent as props, we instead wrap the ChildComponent in a context provider and include the props as value instead. And yes, you do need two sets of curly brackets.

Child Component:

import { useContext } from 'react';
import CountContext from './contexts/CountContext';

const ChildComponent = () => {
  const { count, setCount } = useContext(CountContext);

  return (
    <button onClick={setCount((previousValue) => previousValue + 1)}></button>
    <p>Count is: {count}</p>
  )
}

The difference here is that we're not pulling the props. Instead we're defining them using the context. This is similar to how we define the state hook, but with curly brackets.

Notes

You can create your own Provider, which means you don't have to type in all those values and hope they're right. You can also convert your Context into a custom hook. Because this is just an introduction to Context I haven't done those, but if you're interested they are something you can look up as to how and why you'd do that.

27