Important Update
The Guide Feature will be discontinued after December 15th, 2023. Until then, you can continue to access and refer to the existing guides.
Author avatar

Benney Au

Using React's Context API with Typescript

Benney Au

  • Sep 15, 2020
  • 5 Min read
  • Sep 15, 2020
  • 5 Min read
Web Development
Client-side Frameworks
Front End Web Development


For most React components, you provide data to a child component by manually passing down props through every level of the component hierarchy. When you have a deeply nested hierarchy tree, this becomes cumbersome. React offers the context API as a solution to this issue. You will want to use this over a global variable so that React knows when to re-render your components.

In this guide, you will learn how to use strongly typed React contexts with TypeScript. We will focus on using the Context API inside function components with React Hooks since React Hooks are recommended for new feature development. Throughout this guide, we will use an example that involves storing whether the user has selected a dark or light theme in the context and consuming this context from a deeply nested component. A basic understanding of React Hooks is assumed knowledge for this guide. You can watch this Using React Hooks course if this pattern is new to you.

Set Up a TypeScript React Project

Start by creating a new React project by running the following commands:

1npx create-react-app my-app
2cd my-app
3yarn add typescript
4yarn start

These commands will set up a new project, install TypeScript, and start the local development server.

Create the Context Type Definitions

In order to take advantage of TypeScript, you need to define some types for it to work with. For the purpose of this guide, make the current selected theme and a function that sets the theme available to context consumers.

To do this, create a new file, src/ThemeContext.ts, and add the following code:

1import { createContext, useContext } from 'react';
3export enum Theme {
4    Dark = 'Dark',
5    Light = 'Light',
8export type ThemeContextType = {
9    theme: Theme;
10    setTheme: (Theme: Theme) => void;
13export const ThemeContext = createContext<ThemeContextType>({ theme: Theme.Dark, setTheme: theme => console.warn('no theme provider')});
14export const useTheme = () => useContext(ThemeContext);

There are four definitions in this file:

  • An enum that describes all the possible themes that a user can select. Note that the underlying type is represented as a string. This is easier to debug but still type-safe.
  • ThemeContextType is a second type representing what you can access from the context. It contains the two pieces of data mentioned earlier.
  • The ThemeContext is an object that we will use to provide a context. Here you declare type associated with this context as <ThemeContextType> and its default values. These default values are returned to consumers when there is no theme provider.
  • Finally, useTheme is a custom hook to make consuming the theme and its setter function more convenient. By convention, all hooks are prefixed with use—that's why it is called useTheme.

Use the ThemeContext Provider

You have just created the building blocks for providing and consuming a theme state. Now start providing a theme by wrapping it around the root of your component hierarchy.

First, rename src/App.js to src/App.tsx.

Then change its content to the following:

1import * as React from 'react';
2import './App.css';
3import { ThemeContext, Theme } from './ThemeContext';
4import MyPage from './MyPage';
6function App() {
7  const [theme, setTheme] = React.useState(Theme.Light);
9  return (
10    <ThemeContext.Provider value={{ theme, setTheme }}>
11      <div className="App">
12        <header className="App-header">
13          <MyPage />
14        </header>
15      </div>
16    </ThemeContext.Provider>
17  );
20export default App;

You have wrapped the entire App component with the ThemeContext.Provider. This means that the theme should be accessible from anywhere in the app. The entire app will also be re-rendered if the values in the theme context changes, so it's important not to add frequently changing variables to this context.

Consume the Context From a Nested Component

To consume the theme, use the useTheme hook that you defined earlier. Create a new file, src/MyPage.tsx, and add the following code:

1import * as React from 'react';
2import { useTheme, Theme } from './ThemeContext';
4const MyPage = () => {
5  const { theme, setTheme } = useTheme();
6  console.log(theme);
8  return (
9    <div>
10      <button onClick={() => setTheme(Theme.Dark)}>
11        switch to dark theme
12      </button>
13        my page
14      </div>
15  )
18export default MyPage;

Notice that you have access to the theme and setTheme variables without having to pass those props down manually. In a large app, this can be much more convenient. The theme and setTheme variables are also typed, which is useful for catching bugs.


This guide has demonstrated how to use React's context API with TypeScript to make theme and setTheme globally available and easy to consume. As a final note, you should remember that contexts don't need to be global, and this is not the solution for every state-sharing problem.