DEV Community

Sasha Brockman
Sasha Brockman

Posted on

React createContext and useContext Hooks

When we want to share data between multiple React components, there are a couple of ways to do it. One of the simplest ways to accomplish this is to pass down data from a parent component to a child component as a prop. This, however, can become remarkably tedious when we want to pass data from a parent component to a grandchild component. We end up passing a prop through an entire component only so that the child of that component can use it. This problem only gets worse when we have code with deeply nested components. Luckily, React provides us with a couple of hooks that allow us to share data between any number of components without having to pass it through as props.

createContext()

The first of these hooks is createContext(). To use this hook, we first need to import it, call it, and then assign the return value to a variable. This must be done outside of any component:

import { createContext } from “react”;

const SomeContext = createContext()

Enter fullscreen mode Exit fullscreen mode

The createContext() function takes a default value as a parameter, and if none is provided, it will default to null. The React documentation suggests we always pass a parameter through, even if it’s null, however this is not required for the code to work. This default value is almost never used, however, since the data that we want to share is assigned in the Provider component (more on this in just a bit). createContext() returns a context object that does not really hold any information itself. It simply points to a location from which context will be read or provided. In order to provide data to the context object, we use SomeContext.Provider. In our code, it will look like this:

<SomeContext.Provider value={”some value”}>{children}</SomeContext.Provider>
Enter fullscreen mode Exit fullscreen mode

In this bit of code, ‘some value’ is where we assign our data that we want to share amongst components, and ‘children’ is where we place said components.

useContext()

Now to actually access the data we assigned earlier, we need to use useContext(). Once again, we first need to import the hook and then assign the return value to a variable, but this time we create the variable inside of our component that we want to access the shared data from. Furthermore, we need our SomeContext variable also imported so that we can pass it as a parameter to useContext(). Doing so results in code that looks like this:

import { useContext } from “react”;
import { SomeContext } from “/somewhere”

function SomeComponent(){
    const information = useContext(SomeContext) 

    return (something);
}
Enter fullscreen mode Exit fullscreen mode

Here, we pass our SomeContext variable as a parameter to useContext() so that it knows where to grab data from, and it returns the information that we had previously passed to our component in the value prop.

Additional Usage Information

When using Context from React, there are certain rules that must be followed. First and foremost, we must remember to only use useContext() in our children components. We can have as many children under the parent, however. Doing so will result in code that looks something like this:

const SomeContext = createContext(null);

function App(){
    return(
        <>
            <header>
                <NavBar />
            </header>
            <SomeContext.Provider value={information}>
                <Child1/>
                <Child2/>
                <Child3>
                    <Child4/>
                </Child3>
            </SomeContext.Provider>
        </>
    )
}
Enter fullscreen mode Exit fullscreen mode

In this example, Child1, Child2, Child3, and even Child4 can all access whatever value is assigned to ‘information’. Meanwhile, because NavBar is outside of the Provider component, it cannot access said data. Also, only a single variable can be passed as a prop through the context provider, meaning if we want to provide multiple pieces of information, we will have to assign it either to an Array or Object. From there we can destructure the information within our children components.

useState()

We can combine React Context with the useState() hook not only so that we can access state variables in other components but also allow multiple components to be able to update it.

const SomeContext = createContext();

function App(){
    const [info, setInfo] = useState(some data)

    return(
        <SomeContext.Provider value={{ info, setInfo }}>
            <Child1/>
            <Child2/>
        </SomeContext.Provider>
    )
}
Enter fullscreen mode Exit fullscreen mode

In this example, we are able to call setInfo() in both of the Child components, and doing so will cause the App and subsequent children components to be rerendered.

Conclusion

Luckily, we have Context available to us through React to make our lives easier. When used properly, we have seen how it is able to let us access and alter information across multiple components, all while keeping our code clean and minimal. There are still cases where we do not want to use this to share information, however. Sometimes it is just easier to pass a value as a prop to a couple children instead of going through the entire set up process for Context. While it is not always the right choice for every job, when properly used, it is one of our most versatile tools in React. Hopefully after this short read, you can feel comfortable and ready to use it in your own code.

Sources

useContext: https://react.dev/reference/react/useContext
createContext: https://react.dev/reference/react/createContext
useState: https://react.dev/reference/react/useState

Top comments (0)