# React: how useContext works (with examples)

> How the useContext hook works in React to share data between components without props drilling, with a practical step-by-step example.

- Autore / Author: Diego Betto (https://diegobetto.com/about/)
- Pubblicato / Published: 2023-09-27
- URL: https://diegobetto.com/en/react-usecontext/
- Tag: react, hook, useContext, components, state, props

In React, the useContext hook lets you share data between components, even when they aren't directly connected. This is a simpler and more flexible way to share data compared to the **props drilling** approach.

## Introduction

The useContext hook is a powerful tool that can be used to share data between components in a simple, efficient, and maintainable way.

## How it works

The useContext hook accepts two parameters:

- the context, which is an object representing the data you want to share;
- a selector, which is a function used to get the context's value.

The context is created using the createContext() function.

```js
const ThemeContext = createContext(null);
```

The selector is a function used to get the context's value. The selector can be a simple function that returns the context's value, or it can be a function that processes the context's value.

To use the useContext hook, you need to import it from the React.js package.

```js
import React, { useContext } from "react";
```

Then, you need to use the useContext hook inside the components that need to access the context's data.

```js
const App = () => {
  const theme = useContext(ThemeContext);

  return (
    <div>
      <h1>The current theme is {theme}</h1>
    </div>
  );
};
```

## Example

Here's an example of using the useContext hook to share a theme between components.

```js
import React, { createContext, useState, useContext } from "react";

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState("light");

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>;
};

const App = () => {
  return (
    <ThemeProvider>
      <Content />
    </ThemeProvider>
  );
};

const Content = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div>
      <h1>The current theme is {theme}</h1>
      <Button theme={theme} onClick={toggleTheme}>
        Change theme
      </Button>
    </div>
  );
};

const Button = ({ theme, onClick }) => {
  return (
    <button onClick={onClick} style={{ backgroundColor: theme === "dark" ? "#000" : "#fff" }}>
      {theme}
    </button>
  );
};

export default App;
```

In this example, the context is represented by the `ThemeContext` object. The context is created using the `createContext()` function.

The `ThemeProvider` component is used to provide the context to child components. The `ThemeProvider` component accepts children as a parameter, which is a component that will be rendered inside the context.

```jsx
const ThemeContext = createContext();
```

`createContext` is used to initialize a new React Context. This context can then be used to pass data to various React components without needing to use props.

```jsx
const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState("light");

  // rest of the code
};
```

Let's define a Provider component for our context. This provider will use the React Hook `useState` to create a state that tracks the current theme. The provider will then be used to make this state available to all components that need to access the theme.

```jsx
const App = () => {
  return (
    <ThemeProvider>
      <Content />
    </ThemeProvider>
  );
};
```

Let's wrap our entire application content inside `ThemeProvider`. This lets us access the theme state in all child components.

```jsx
const Content = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  // rest of the code
};
```

We use the React Hook `useContext` to access the theme state and the function to change it.

```jsx
const Button = ({ theme, onClick }) => {
  // rest of the code
};
```

This is a simple Button component that receives the current theme and an onClick function as props. The button's background color changes depending on the theme.
Note: If you think you'll be using the theme in many different places in your code, it can be useful to make the theme context available through a custom Hook. This can simplify access to the theme context.

## Advantages

Using the useContext hook offers several advantages over the props drilling approach.

- It's simpler and more flexible. You don't need to pass data from one component to another, you just need to use the `useContext()` hook to get the context's value.
- It's more efficient. The `useContext()` hook runs only once, when the component mounts.
- It's more maintainable. The code is easier to understand and maintain, since you don't need to keep track of the props chain.

## Conclusion

The `useContext` hook is a powerful tool that can be used to share data between components in a simple, efficient, and maintainable way.

If you're interested in seeing `useContext` combined with `useState` in a practical case, I've also written a dedicated example on [useContext with useState](https://diegobetto.com/react-usecontext-usestate/). If your state is more complex instead, take a look at the guide to [useReducer](https://diegobetto.com/react-usereducer/).
