Mastering the React.js useContext Hook ๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป

Mastering the React.js useContext Hook ๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป

In this article, we will be covering the basics of using the useContext hook in React. Suitable for React beginners looking to write cleaner code.

ยท

9 min read

Introduction:

The useContext hook is a powerful tool in React that allows you to easily share data between components without the need for props drilling. This can make your code more readable, maintainable and efficient.

Before the useContext hook was introduced, developers had to pass data down through multiple levels of components using props, which can quickly become tedious and confusing. With the useContext hook, you can create a context that can be accessed by any component in your application, making it easy to share data across your entire app.

In this article, we will be covering the basics of using the useContext hook, including how to set up a context, how to access the context using the useContext hook, how to update the context, and a real-world example of how to use it in your application. We will also be discussing best practices for using the useContext hook and where it may not be the best solution.

Whether you are a beginner or an experienced React developer, this article will provide valuable information on how to use the useContext hook in your application. So, let's dive in and learn how to use this powerful tool to make your code more efficient and easy to understand.

Setting up a Context:

The first step in using the useContext hook is to set up a context. This can be done using the React.createContext method. This method takes an initial value as an argument and returns an object with two components: Provider and Consumer.

const MyContext = React.createContext(initialValue);

The Provider component is used to provide the context value to all components that are descendants of it. The Provider component takes a value prop that is used to set the context value.

<MyContext.Provider value={contextValue}>
  {/* Components that need access to the context */}
</MyContext.Provider>

It is important to note that the Provider component should be placed at the highest level in your component tree where all components that need access to the context are descendants. This way, the context value is easily accessible to all components that need it.

The Consumer component is used to access the context value in a class component. However, in this article we will be focusing on using the useContext hook in functional components.

Once you have set up your context and provided it to your components using the Provider component, your components will have access to the context value and can use it to determine their behavior.

It's worth mentioning, that the initial value can be any type, from a simple string to an object, it all depend on your use case. And if you don't provide an initial value, it will be undefined and spit out an error.

In summary, setting up a context in React involves:

  • using the React.createContext method to create a context

  • using the Provider component to provide the context value to all descendant components

  • placing the Provider component at the highest level in your component tree where all components that need access to the context are descendants.

Using the useContext Hook:

Now that we have set up our context and provided it to our components, we can use the useContext hook to access the context value in a functional component. The useContext hook takes the context object as an argument and returns the current context value.

const contextValue = useContext(MyContext);

Once you have the context value, you can use it in your component to determine its behavior. For example, you could use the context value to set the value of a state variable, or to conditionally render a certain element.

function MyComponent() {
  const theme = useContext(MyContext);

  return (
    <div className={`theme-${theme}`}>
      {/* content */}
    </div>
  );
}

It's important to note that the useContext hook only updates the component when the context value changes. This means that if the context value is an object or an array, the component will not re-render if the object or array is mutated. To force a re-render, you should create a new object or array with the updated values.

Another thing to keep in mind is that if you try to use the useContext hook in a component that is not a descendant of the Provider component, the hook will return the initial value that was passed to the React.createContext method.

So to summarize:

  • using useContext hook to access the context value in a functional component by passing context object as an argument

  • using the returned value to determine the component behavior

  • keep in mind that when the context value is an object or an array, the component will not re-render if the object or array is mutated, so you should create a new object or array with the updated values.

  • also, if you try to use the useContext hook in a component that is not a descendant of the Provider component, the hook will return the initial value that was passed to the React.createContext method.

In this section, we have learned how to access the context value using the useContext hook, and how to use it to determine the behavior of our component. In the next section, we will learn how to update the context value and how it flows through the application.

Updating the Context:

Once a context has been set up and is being accessed by components using the useContext hook, it's important to know how to update the context value. Updating the context value can be done by modifying the value prop of the Provider component and re-rendering the component.

function MyProvider({ initialValue }) {
  const [value, setValue] = useState(initialValue);

  return (
    <MyContext.Provider value={value}>
      <button onClick={() => setValue(newValue)}>Change Value</button>
      {/* other components */}
    </MyContext.Provider>
  );
}

In the example above, we are using the useState hook to keep track of the context value and a button to change the value. When the button is clicked, the setValue function is called with the new value, which causes the component to re-render and updates the context value for all components that are using it.

It's important to note that updating the context value will cause all components that are using the context to re-render. This means that if you update the context value unnecessarily, it can lead to poor performance. To avoid this, you should only update the context value when it's necessary and make sure to use the shouldComponentUpdate lifecycle method or the useEffect hook with proper dependencies to prevent unnecessary re-renders.

Additionally, when updating a context value that is an object or an array, make sure to create a new object or array with the updated values, as mentioned before, to force a re-render.

In summary:

  • updating the context value can be done by modifying the value prop of the Provider component and re-rendering the component

  • updating the context value will cause all components that are using the context to re-render

  • to avoid unnecessary re-renders, you should only update the context value when it's necessary and use the shouldComponentUpdate lifecycle method or the useEffect hook with proper dependencies

  • and when updating a context value that is an object or an array, make sure to create a new object or array with the updated values.

In this section, we have learned how to update the context value and how it flows through the application. In the next section, we will see an example of how to use the useContext hook in a real-world scenario.

Real World Example:

In this section, we will be looking at an example of how to use the useContext hook in a real-world scenario. Let's imagine we are building a simple application that has a dark/light theme toggle feature. We will be using the useContext hook to share the theme information between components.

First, we will create a context for our theme using the React.createContext method and set an initial value of "dark".

const ThemeContext = React.createContext("dark");

Next, we will create a component called ThemeToggler that will be responsible for changing the theme. This component will be a stateful component that uses the useState hook to keep track of the current theme. It will also render a button that when clicked, will toggle the theme between "dark" and "light".

Copy codefunction ThemeToggler() {
  const [theme, setTheme] = useState("dark");

  return (
    <>
      <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
        Toggle Theme
      </button>
      <ThemeContext.Provider value={theme}>
        {/* other components */}
      </ThemeContext.Provider>
    </>
  );
}

Now, we will create a component called App that will be the parent of all other components. Inside App, we will render the ThemeToggler and other components that need access to the theme.

function App() {
  return (
    <div className="App">
      <ThemeToggler />
      <Content />
    </div>
  );
}

Finally, we will create a component called Content that will display some text and change the background color depending on the theme. This component will use the useContext hook to access the theme value.

function Content() {
  const theme = useContext(ThemeContext);
  const className = theme === "dark" ? "dark-theme" : "light-theme";

  return (
    <div className={className}>
      <h1>Hello World!</h1>
    </div>
  );
}

In this example, we have created a simple application that has a dark/light theme toggle feature. We have used the useContext hook to share the theme information between components. The ThemeToggler component is responsible for changing the theme, and the App and Content components use the theme value to determine their behavior.

It's worth noting that in this example, we are using the useState hook in the ThemeToggler component to keep track of the theme state, and then use the useContext hook in the other components to consume that state. However, it's possible to use useReducer hook instead of useState to manage the state and the context in one place and make it more manageable.

In summary, this example demonstrates how to use the useContext hook to share data between components and how to update the context value to change the behavior of the components. This example also shows how to use the useState hook to keep track of the context value, but also how it can be replaced with useReducer for more complex cases.

Conclusion:

In this article, we have covered the basics of using the useContext hook in React. We have learned how to set up a context, how to access the context using the useContext hook, how to update the context and when to use it. We also looked at a real-world example of how to use the useContext hook in a simple application.

We have seen that the useContext hook is a powerful tool that allows you to easily share data between components without the need for props drilling. This can make your code more readable, maintainable and efficient. However, it's important to keep in mind that updating the context value will cause all components that are using the context to re-render, so you should only update the context value when it's necessary, and use the shouldComponentUpdate lifecycle method or the useEffect hook with proper dependencies to prevent unnecessary re-renders.

As always, it's important to understand the trade-offs of each approach and use the right tool for the job. The useContext hook can be a great solution for sharing data between components, but it may not be the best solution for every use case.

If you are looking to learn more about the useContext hook and other React concepts, there are many resources available online. The official React documentation is a great place to start, as well as other tutorials and blog posts on the topic.

Thank you for reading, and I hope you found this article helpful in your journey to becoming a better React developer.โœŒ๏ธ๐Ÿ’ป

ย