React useContext() Hook Example

Overview

This post is a short walk thru of a small app that demonstrates the useContext() hook. The useContext() hook provides a convenient way to share a state variable between multiple components. The example application will consist of three components. The context is declared in the Parent component and passed to the Input and Output components. The Input component changes the state and is rendered in the Output component.

Getting Started

Create the application

npx create react-app react-context-demo

Use Case

Traditionally react developers will use a hook like useState() to handle the state, then pass it to the child components along with a handler to update the state (below).

Example:

const [username, setUsername ] = useState('');
...
const handleNameChange = (newValue) => {
    setUsername(newValue)
}
...
return (
   <ChildComponent name={name} handleChange={handleUsernameChange} />
)

In simple cases this is a reasonable solution to implement. When the application has several or more state variables being shared by multiple components, you have to pass the state and event handlers to multiple levels and the code will become difficult to maintain.

useContext() along with createContext() make the above scenario more maintainable. Of course, you can dive off the deep end and use an advance state management library/pattern such as Redux, Find out more about redux from an earlier article available here.

Parent Component

The parent component creates the context variables and wraps the child components with an AppContext.Provider tag. The example below creates the context for username and setUsername(). Both will be available in the child components, thus either can get and change the state without having to call a handler in the parent component or use redux etc.

Code for ParentComp.js

import { createContext, useState } from 'react';
import LevelTwoCompOne from './InputComp'
import InputComp from './OutputComp'

export const AppContext = createContext(null);

export default function ParentComp() {
    const [username, setUsername] = useState('danny123');
    return (
        <div>
            <AppContext.Provider value={{username, setUsername}}>
                <LevelTwoCompOne /> 
                <InputComp />
            </AppContext.Provider>            
        </div>
    )
}

Input Component

The InputComp.js component get the setUsername() via useContext() hook and can set the state.

Code for InputComp.js

import { useContext } from 'react'
import { AppContext } from './ParentComp';

export default function InputComp() {
    const { setUsername } = useContext(AppContext)
    return (
        <div>
            <input onChange={(e) => setUsername(e.target.value)}></input>
        </div>
    )
}

Output Component

OutputComp.js gets the state of username with the useContext() as well and displays the value that can be changed in the InputComp.js up above.

Code for OutputComp.js


import { useContext } from 'react'
import { AppContext } from './ParentComp';

export default function OutputComp() {
    const { username } = useContext(AppContext)
    return (
        <div>
            Username: {username}
        </div>
    )
}