ReactJS - Using useContext



Context is one of the important concept in React. It provides the ability to pass a information from the parent component to all its children to any nested level without passing the information through props in each level. Context will make the code more readable and simple to understand. Context can be used to store information which does not change or have minimal change. Some of the use cases of context are as follows −

  • Application configuration

  • Current authenticated user information

  • Current user setting

  • Language setting

  • Theme / Design configuration by application / users

React provides a special hook, useContext to access and update the context information in the function component. Let use learn context and its corresponding hook in this chapter.

How context works?

Before understanding useContext hook, let us revisit the basic concept of context and how it works. Context has four parts,

  • Creating a new context

  • Setting context provider in the root component

  • Setting context consumer in the component where we need the context information

  • Accessing context information and using it in render method

Let us create an application to better understand context and its usage. Let us create a global context for maintaining theme information in the application root component and use it in our child component.

First of all, create and start an application using below command,

create-react-app myapp
cd myapp
npm start

Next, create a component, HelloWorld under components folder (src/components/HelloWorld.js)

import React from "react";
import ThemeContext from "../ThemeContext";
class HelloWorld extends React.Component {
   render() {
      return <div>Hello World</div>
   }
}
export default HelloWorld

Next, create with a new context (src/ThemeContext.js) for maintaining theme information.

import React from 'react'
const ThemeContext = React.createContext({
   color: 'black',
   backgroundColor: 'white'
})
export default ThemeContext

Here,

  • A new context is created using React.createContext.

  • Context is modeled as an object having style information.

  • Set initial value for color and background of the text.

Next, update the root component, App.js by including HelloWorld component and the theme provider with initial value for the theme context.

import './App.css';
import HelloWorld from './components/HelloWorld';
import ThemeContext from './ThemeContext'
function App() {
   return (
      <ThemeContext.Provider value={{
         color: 'white',
         backgroundColor: 'green'
      }}>
      <HelloWorld />
      </ThemeContext.Provider>
   );
}
export default App;

Here, the ThemeContext.Provider is used, which is a non-visual component to set the value of the theme context to be used in all its children component.

Next, include a context consumer in HelloWorld component and style the hello world message using theme information in HelloWorld component.

import React from "react";
import ThemeContext from "../ThemeContext";
class HelloWorld extends React.Component {
   render() {
      return  (
         <ThemeContext.Consumer>
         {
            ( {color, backgroundColor} ) =>
            (<div style={{
               color: color,
               backgroundColor: backgroundColor }}>
               Hello World
            </div>)
         }
      </ThemeContext.Consumer>)
   }
}
export default HelloWorld

Here we have,

  • Used ThemeContext.Consumer, which is a non-visual component providing access to the current theme context details

  • Used a function expression to get the current context information inside ThemeContext.Consumer

  • Used object deconstruction syntax to get the theme information and set the value in color and backgroundColor variable.

  • Used the theme information to style the component using style props.

Finally, open the browser and check the output of the application

ReactJS Using UseContext

Signature of useContext

The signature of the useContext is as follows −

let contextValue = useContext( <contextName> )

Here,

  • contextName refers the name of the context to be accessed.

  • contextValue refers the current value of the referred context.

An example code to access the context using hooks is as follows −

const theme = useContext(ThemContext)

Context usage through hook

Let us update our application and use the context hook instead of context consumer.

First of all, convert the HelloWorld component into function component.

import React from "react";
function HelloWorld() {
   return <div>Hello World</div>
}
export default HelloWorld

Next, access the current value of the context through useContext hook

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let theme = useContext(ThemeContext)
   return <div>Hello World</div>
}
export default HelloWorld

Next, update the rendering function to use the theme information fetched through context.

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let theme = useContext(ThemeContext)
   return (
      <div style={{
         color: theme.color,
         backgroundColor: theme.backgroundColor }}>
            Hello World
      </div>
   )
}
export default HelloWorld

Here we have,

  • Used useContext to access the ThemeContext context information.

  • Used ThemeContext information to set background color and color of the text.

Finally, open the browser and check the output of the application.

Context Usage Through Hook

Updating context

In some scenarios, updating the context information is necessary. For example, we may provide an option to change the theme information by user. When user changes the theme, then the context should get updated. Updating the context will rerender all the child component, which will change the theme of the application.

React provides an option to update the context by using both useState and useContext hook. Let us update our application to support theme selection.

First of all, update the root component, App.js and use useState hook to manage the theme information as shown below −

import './App.css'
import { useState } from 'react'
import HelloWorld from './components/HelloWorld'
import ThemeContext from './ThemeContext'
function App() {
   let initialTheme = {
      color: 'white',
      backgroundColor: 'green'
   }
   const [theme, setTheme] = useState(initialTheme)
   return (
      <ThemeContext.Provider value={{ theme, setTheme }}>
         <HelloWorld />
      </ThemeContext.Provider>
   );
}
export default App;

Here we have,

  • Used useState hook to set the theme information in the state of the root component.

  • Theme update function, useTheme returned by useState is also included as part of theme information in the context.

Next, update the HelloWorld component to get the theme information stored in the context.

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let { theme, setTheme } = useContext(ThemeContext)
   return (<div style={{
            color: theme.color,
            backgroundColor: theme.backgroundColor }}>
         <div>Hello World</div>
      </div>)
}
export default HelloWorld

Next, provide an option for the user to change the theme through a drop down option.

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let { theme, setTheme } = useContext(ThemeContext)
   return (<div style={{
      color: theme.color,
      backgroundColor: theme.backgroundColor }}>
   <div>
      <select value={theme.backgroundColor}>
         <option value="green">Green</option>
         <option value="red">Red</option>
      </select>
      <div>Hello World</div>
   </div>)
}
export default HelloWorld

Here we have,

  • Added a dropdown box with two options, Green and Red.

  • Set the current value of the dropdown box using the current theme value value={theme.backgroundColor).

Next, update the context whenever the theme is changed by the user through onChange event.

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let { theme, setTheme } = useContext(ThemeContext)
   return (<div style={{
      color: theme.color,
      backgroundColor: theme.backgroundColor }}>
   <div>
      <select value={theme.backgroundColor}
         onChange = {
            (e) => {
               setTheme({
                  ...theme,
                  backgroundColor: e.target.value
               })
            }} >
         <option value="green">Green</option>
         <option value="red">Red</option>
      </select>
   </div>
      <div>Hello World</div>
   </div>)
}
export default HelloWorld

Here we have,

  • Attached an onChange event to the dropdown box.

  • Used the setTheme function inside the event handler and updated the background color of the theme to the color selected by the user.

The complete code of the root component and HelloWorld component are as follows &miinus;

import React, { useContext } from "react"
import ThemeContext from '../ThemeContext'
function HelloWorld() {
   let { theme, setTheme } = useContext(ThemeContext)
   return (<div style={{
      color: theme.color,
      backgroundColor: theme.backgroundColor }}>
   <div>
      <select value={theme.backgroundColor}
         onChange= {
            (e) => {
               setTheme({
                  ...theme,
                  backgroundColor: e.target.value
               })
            }
         } >
         <option value="green">Green</option>
         <option value="red">Red</option>
      </select>
   </div>
      <div>Hello World</div>
   </div>)
}
export default HelloWorld

Next, open the browser and check the application.

Updating Context

When user selected a different background color, it will update the context and consequently, it will rerender the component will new theme as shown below −

Updating Context

Summary

Context reduces the complexity of maintaining global data in a react application. Context hook further reduces the complexity by simplifying the accessing and updating (through useState) the context.

Advertisements