Skip to content

Understanding why and how to use React's Context hook

Posted on:July 20, 2023 at 10:57 AM
Reading time:6 minutes

Hello there, fellow explorers of the code universe! Today, we are going to demystify an exciting feature of the React.js library: the Context hook. Don’t worry if this sounds intimidating; I’ll do my best to explain it in simple, easy-to-understand terms.

Table of contents

Open Table of contents

What is the React Context hook?

Before we delve into the Context hook, let’s take a step back and understand what “context” is in the React universe. If you’ve been around the block with React, you might’ve heard about “props”. Props allow us to pass data down from parent components to their children. It’s a little like how your grandparents passed down those stories that you share with your kids.

But what if you wanted to share those stories with your cousin who lives a few houses down? In the world of React, that would mean passing the data through many components that might not even need that data! This is where React’s context system comes into play. The context system allows you to share data through the component tree without having to pass props down manually at every level. In our analogy, it’s like your grandparent’s stories being broadcast on the local radio station for all the family members to listen to!

React’s useContext() hook is a function that lets you tap into this shared data (or context) from any function component. You can think of it as tuning into the radio station where the stories are being broadcast.

Why use the Context hook?

As our React applications grow bigger, managing state and passing data becomes increasingly complex. The Context hook is a powerful way to share data across multiple levels of the application without resorting to “prop drilling” (passing data through numerous components via props).

Also, using context can help us structure our code more cleanly and increase its reusability. It makes it easier to maintain large applications, as components can directly access the data they need from the context.

How to use the Context hook

To give you a hands-on understanding, let’s create an example where we use the Context hook to create a Context which stores a user’s search input so that it can be accessed by all components with access when needed.

Create the Context

First, we need to create our context using createContext(). This returns a context object.

import { createContext } from "react";

const SearchContext = createContext(null);

Provide the Context

Now, we wrap the part of our component tree that needs access to the context data in a SearchContext.Provider component. This allows any child components to access the context.

// write your own logic to get user input and store it in variable "search"
// then store it in an object in the Context Provider "value" prop as per below
<SearchContext.Provider value={{ search }}>
  <App />
  // in this case we are giving access to all child components of the entire App
  component
</SearchContext.Provider>

Consume the Context

Inside our function component, we use the useContext() hook to access the provided context.

import { useContext } from "react";

const MyComponent = () => {
  const { search } = useContext(SearchContext);
  return <p>{search}</p>;
};

In MyComponent(), we use useContext(SearchContext) to get the value provided in SearchContext.Provider. We then use this to simply display the user “search” input in a <p>.

And voila! You’ve just used the Context hook in React!

In practice

While the above example works and is completely great, I personally like to export a component that is a little more digestible instead of creating and providing the Context directly in some component. Inside a new file search-context.js for example:

import { createContext, useContext } from "react";

const SearchContext = createContext(null);

const SearchProvider = ({ children }) => {
  // once again, as per above, define your own logic to get user input and store it in variable "search"
  // then store it in an object in the Context Provider "value" prop as per below
  return (
    <SearchContext.Provider value={{ search }}>
      {children}
    </SearchContext.Provider>
  );
};

const useSearch = () => useContext(SearchContext);

export { SearchProvider as default, useSearch };

Now inside the component file we want to wrap with the context, we can import our SearchProvider.

// inside _app.js file in Next.js for example
import SearchProvider from "./search-context.js";

export default function App({ Component, pageProps }) {
  return (
    // looks cleaner :)
    <SearchProvider>
      <Component {...pageProps} />
    </SearchProvider>
  );
}

And finally, if we want to consume the Context anywhere in the child component of the App() component, we can use the useSearch() function we exported in the search-context.js file.

import { useSearch } from "./search-context.js";

const MyComponent = () => {
  const { search } = useSearch();
  return <p>{search}</p>;
};

Looks much cleaner to me!

Wrapping Up

To wrap up, the Context hook in React.js is a powerful tool for sharing data across multiple components without having to pass props manually through each level. It is particularly useful in large applications where state management could become complex. By using the Context hook, we can write cleaner, more maintainable, and more reusable code.

Remember, though, with great power comes great responsibility. It might be tempting to use context for all state in your app, but it’s often better suited to “global” state that many components need to access. For individual component state, React’s useState() or useReducer() hooks are often a better choice.

Happy coding!

References