[React] Context API

2021-07-01 hit count image

Let's see how to use Context API to manage the global data in React.

Outline

To manage the data in React, you can use Props, State and Context. In this blog post, I will introduce what Context is and How to use it.

If you want to know details about Props and State, see the link below.

You can see full source code of the blog post on the link below.

Context

In React, Props and State are used for managing the data from the parent component to the child component. When you use the Props and State, the data flows from the parent component and the child component, that is, from top to bottom and to one way.

React data flow with Props

What should you do if you want to use data flowing one direction or insert data that is used by another component into the current data flow?

React need data in another data flow

In React, the data flows from top to bottom, so to solve this problem, you can create State for data in the common parent component and pass the data via Props to the child component.

React global data with props and state

However, It’s very inefficient to create State and pass it by Props for every time when we need to share the data between components. To solve this issue, React introduces Flux concept and provide Context API for Flux.

Context is used to handle global data regardless of the data flow passed from the parent component to the child component. We can store global data to Context, and get the data on the component that needs it.

React context

To use Context in React, you need to use Context API, especially you need to use Provider and Consumer of Context API.

React context with Provider and Consumer

To use the data stored in Context, we need to provide Context Provider to the common parent component, and we need to use Context consumer to consume the data in the component that needs it.

How to use Context

Now, let’s see how to use Context API to handle global data in React.

Prepare project

Execute the command below to create a new React project for Context.

npx create-react-app context_example --template=typescript

Create Context

Next, let’s create a Context to store global data. Create./src/Contexts/Count/index.tsx file and modify it like the below.


import { createContext, useState } from 'react';

const CountContext = createContext({
  count: 0,
  plusCount: () => {},
});

interface Props {
  children: JSX.Element | JSX.Element[];
}

const CountProvider = ({ children }: Props): JSX.Element => {
  const [count, setCount] = useState(0);

  const plusCount = (): void => {
    setCount(count + 1);
  };

  return (
    <CountContext.Provider
      value={{
        count,
        plusCount,
      }}>
      {children}
    </CountContext.Provider>
  );
};

export { CountContext, CountProvider };

To create Context in React, we need to use createContext. Also, Context is also a React component, so we need to use State to handle the mutable data in the component.

import { createContext, useState } from 'react';

Next, create Context by createContext. At this time, we need to pass the initial value of the global data.

const CountContext = createContext({
  count: 0,
  plusCount: () => {},
});

Context is also one of the React component, so the structure of Context is basically same with the component. At this time, we need to wrap the content to be displayed on the screen with Context Provider.

...
const CountProvider = ({ children }: Props): JSX.Element => {
  ...
  return (
    <CountContext.Provider>
      {children}
    </CountContext.Provider>
  );
};

export { CountContext, CountProvider };

Context is also the React component. So, when we use the changeable data in Context, we need to use useState to create State.


const CountProvider = ({ children }: Props): JSX.Element => {
  const [count, setCount] = useState(0);

  const plusCount = (): void => {
    setCount(count + 1);
  };
  ...
};

And then, we need to provide State to Context Provider.


const CountProvider = ({ children }: Props): JSX.Element => {
  ...
  return (
    <CountContext.Provider
      value={{
        count,
        plusCount,
      }}>
      {children}
    </CountContext.Provider>
  );
};

Lastly, export Context created by createContext and the React component created by Context Provider. the React component created by Context Provider will be used on the common parent component, and Context created by createContext will be used to consume data.

export { CountContext, CountProvider };

Done! we’ve created Context for global data. Next, let’s see how to use Context.

Provider

To use Context, we need to provide Context Provider to the common parent component. In here, we’ll provide it to the App component. To provide Context Provider, open the ./src/App.tsx file and modify it like the below.

import { CountProvider } from './Contexts/Count';

import { CountLabel } from './Components/CountLabel';
import { PlusButton } from './Components/PlusButton';

function App() {
  return (
    <CountProvider>
      <CountLabel />
      <PlusButton />
    </CountProvider>
  );
}

export default App;

To use global data with Context, we need to provide Context Provider to the common parent component. Providing Context Provider means to wrap the component with it.

import { CountProvider } from './Contexts/Count';
...
function App() {
  return (
    <CountProvider>
      ...
    </CountProvider>
  );
}

export default App;

Now, we can access global data in Context on any component under CountProvider.

...
import { CountLabel } from './Components/CountLabel';
import { PlusButton } from './Components/PlusButton';

function App() {
  return (
    <CountProvider>
      <CountLabel />
      <PlusButton />
    </CountProvider>
  );
}

We didn’t create the components that use Context, so errors occur. Next, let’s create the CountLabel component and PlusButton component to use Context data.

Consumer

Let’s make components to use global data in Context. First, create ./src/Components/CountLabel/index.tsx file and modify it like the below.

import { useContext } from 'react';
import { CountContext } from '../../Contexts/Count';

export const CountLabel = () => {
  const { count } = useContext(CountContext);
  return <div>{count}</div>;
};

The CountLabel component is a simple component to show the count on the screen. we’ll use the global data in Context for the count value in here. When you use the value in Context, you should use Consumer in the React class component and useContext hook in the function component.

We need to pass CountContext that is our Context to the parameter, and then we can access the variables that we’ve created them by createContext.

const CountContext = createContext({
  count: 0,
  plusCount: () => {},
});

CountLabel only needs the count variable in Context.

...
export const CountLabel = () => {
  const { count } = useContext(CountContext);
  return <div>{count}</div>;
};

Next, let’s create the PlusButton component to increase the count value in Context. Create the ./src/Components/PlusButton/index.tsx file and modify it like the below.

import { useContext } from 'react';
import { CountContext } from '../../Contexts/Count';

export const PlusButton = () => {
  const { plusCount } = useContext(CountContext);

  return <button onClick={plusCount}>+ 1</button>;
};

The PlusButton component is a simple component to show the + 1 label button and when the button is clicked, call the plusCount fucntion to increase the count value in Context.

Like CountLabel, we use useContext hook to get the plusCount function to increase the count value in Context, and then, we bound the function to the onClick event.

Check

We’ve made the example to use global data with Context. To check the React project we’ve created, execute the command below to start the React project.

npm start

When the React project is started, you can see the 0 lable and + 1 button on the screen like the below.

React Context example: Count

When you click the + 1 button, you can see the count value is increased like the below.

React Context example: Count increased

Completed

Done! we’ve seen how to handle global data in the React component with Context. The example in the blog post is very small, so actually, we don’t need to use Context. However, if the project has many components, you can see Context to share the data, so someday this blog post about how to use Context is helpful for you.

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

Posts