How to use context in React - 2

One of Reacts last new features are the Hooks API's and, they really shine when creating function components. One of the Hooks is called useContext and in this article I'm describing a simple solution how to use it instead och the traditional way that I wrote about in part 1 in this mini tutorial.

Use useContext hook API

React's Context is initialized with React's createContext top level API. In this tutorial we are using the context to share a theme across the application. To keep it simple, the theme in this tutorial will be only a color. A theme could of course contain much more such as padding, margin, font-sizes, etc.

Demonstration of creating a context.

// src/ThemeContext.js

import React from 'react'

// We are not specifying any default value
const ThemeContext = React.createContext(null)
export default ThemeContext

After we have created a context, in component A, we are using the provider API from the context API to provide a color value in the context object.

// src/ComponentA.js
import React from 'react'

// Import the context
import ThemeContext from './ThemeContext'

const A = () => (
  // Give the context provider a color value
  <ThemeContext.Provider value="green">
    <D />
  </ThemeContext.Provider>
)

The component A is now implicit a theme provider ensuring all components below it, has access to the theme's context, eg, Somewhere below component A, not component D in this case, but any other child component, let's say component C, will use this theme to style itself:

// src/ComponentC.js

import React from 'react'

// Import the context
import ThemeContext from './ThemeContext'

const C = () => (
  // Consume the context
  <ThemeContext.Consumer>
    {color => (
      <p style={{ color }}>
        Hello World
      </p>
    )}
  </ThemeContext.Consumer>
)

That's the most basic approach of using context API with a single top-level Provider component and one Consumer component in a child component sitting somewhere below. There can be many more child components using the Consumer component though, but they have to be located somewhere below the component using the Provider component.

Now comes the crucial part where we shift towards React's useContext Hook. As you can see, the Consumer component coming from React's Context is by default a render prop component. In a world where we can use React Hooks, a render prop component isn't always the best choice. Let's see the previous example with React's useContext Hook instead:

// src/ComponentC.js
import React, {useContext} from 'react'

// Import the context
import ThemeContext from './ThemeContext'

const C = () => {
  // useContextHook hook to get the value
  const color = useContext(ThemeContext);
  return (
    <p style={{ color }}>
      Hello World
    </p>
  )
}

React's useContext just uses the Context object created before and retrieve the most recent value from it. Using the React Hooks instead of the Consumer component makes the code much more readable, less verbose, and doesn't introduce a kinda artificial component via the Consumer component in between.


Published: 2019-11-13
Author: Henrik Grönvall
Henrik Grönvall
Copyright © 2022 Henrik Grönvall Consulting AB