DEV Community

Cover image for React basics: explaining the useContext hook
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

React basics: explaining the useContext hook

Sometimes we have data that we need to access in almost all parts of our components.

It will become a hassle to pass them down to each component, exactly where context comes in.

In this example, I'll use a specific theme for a website.
Our website has a blue and a red theme, which the user can toggle based on their preferences.

Creating a context

Before we can do anything, we need to create a new context to wrap around our application.

So, let's look at how that works, create a new file called ThemeContext.js and start by adding the imports we need.

import { createContext, useState } from 'react';
Enter fullscreen mode Exit fullscreen mode

Now let's define our themes, this is still pretty hardcoded, but it will work fine for this demo.

const themes = {
  blue: {
    background: 'blue',
    color: 'white',
  },
  red: {
    background: 'red',
    color: 'black',
  },
};
Enter fullscreen mode Exit fullscreen mode

As you can see, we have a blue and a red theme.

The first thing we need to do now is create an actual context with a default value.
In my case, I want the red theme to be the blue theme to be the default.

export const ThemeContext = createContext(themes.blue);
Enter fullscreen mode Exit fullscreen mode

And then, we can export a ThemeProvider which helps us wrap this theme around our app.

export function ThemeProvider(props) {
  return (
    <ThemeContext.Provider value={themes.blue}>
      {props.children}
    </ThemeContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

This provider can now be wrapped around our app to apply the context. Let's head over to our App.js file and do that.

import { ThemeProvider } from './context/ThemeContext';

function App() {

  return (
    <ThemeProvider>
      <div className='App'>
        The rest of our app
      </div>
    </ThemeProvider>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This gives us access to anything in the theme.

Using the context

Pretty cool, but how do we now use this context?

Create a sample component that will act as our paint. This component will take the context and display the correct color.

import { useContext } from 'react';
import { ThemeContext } from '../context/ThemeContext';

export default function Paint() {
  const theme = useContext(ThemeContext);

  return (
    <div
      style={{
        background: theme.background,
        color: theme.color,
        padding: '2rem',
      }}
    >
      I'm the paint
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This component will render a simple div, with colors based on whatever our theme is.

Head back to your App and include this component.

import Paint from './components/Paint';

return (
    <ThemeProvider>
      <div className='App'>
        <Paint />
      </div>
    </ThemeProvider>
);
Enter fullscreen mode Exit fullscreen mode

You should now see the block in your browser like so:

Basic context painted component in React

If we now change our ThemeContext to be red, we should see a red box.

<ThemeContext.Provider value={themes.red}>
Enter fullscreen mode Exit fullscreen mode

Changed context provider in React

Adding a toggle

This is pretty exciting stuff already, but it becomes super powerful by adding a dynamic switch for our theme.

Let's say we want to render two buttons. Each button will set a different theme.

To do this, we first have to use useState in our ThemeContext file.

import { createContext, useState } from 'react';

export function ThemeProvider(props) {
  const [theme, setTheme] = useState('blue');

  const themeProviderData = {
    theme: themes[theme],
    setTheme: (theme) => setTheme(theme),
  };

  return (
    <ThemeContext.Provider value={themeProviderData}>
      {props.children}
    </ThemeContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

As you can see, I use the useState function to now set a basic theme (blue).
Then I create a primary object containing the current theme data and pass the setState function to modify the state variable.
Then we pass this object as the value of our theme.

One thing to note here is that we changed from passing a single variable to passing an object.

So head over to your Paint component and change the import like so:

const { theme } = useContext(ThemeContext);
Enter fullscreen mode Exit fullscreen mode

Then we can go ahead and create a new component called Toggle.

import { useContext } from 'react';
import { ThemeContext } from '../context/ThemeContext';

export default function Toggle() {
  const { setTheme } = useContext(ThemeContext);

  return (
    <>
      <button onClick={() => setTheme('red')}>RED THEME</button>
      <button onClick={() => setTheme('blue')}>BLUE THEME</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

As you can see, this function extracts the setTheme function from our context.
It then renders two buttons and appends this function with a specific value.

Go ahead and include this component in your App like so:

import Toggle from './components/Toggle';

function App() {
  return (
    <ThemeProvider>
      <div className='App'>
        <Paint />
        <Toggle />
      </div>
    </ThemeProvider>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

And there we have it. We can now toggle between our two themes!

Switching context in React

I've also added this project on GitHub if you want to see more details.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Discussion (2)

Collapse
waylonwalker profile image
Waylon Walker

It's been quite awhile since I have used react, but this was one of the topics that really confused me at the time, and it was so magical when it was up and working.

Collapse
dailydevtips1 profile image
Chris Bongers Author

Yeah definitely helps if you keep working on these things and exploring them.