Context and the useContext hook.
Tags: react
Published: 2020-02-02 18:50:30

_image from https://www.udemy.com/course/react-hooks-tutorial/_

In this tutorial we are going to be making a basic app with context so that the user can enjoy dark mode in your react app.

__Why is this helpful?__

this is helpful because context allows you to scale your applications without having to pass props between components that don't need them. 

As it stands this is the simplest way I have come across to make context.

__How you should use this tutorial?__

you should try and go through this tutorial with as little referencing as possible. Come up with your own way of setting up context using hooks, then practice until you can do this from memory. 

__prerequisites:__

1. basic knowledge of javascript

2. basic knowledge of react

3. [create react app](https://www.npmjs.com/package/create-react-app) installed globally on your computer.

4. a text editor, I use [VS code.](https://code.visualstudio.com/download)

__getting started.__

create a new react app by running this command in your command-line.

```bash
create-react-app use-context-tutorial

```

open the folder. 

```bash
cd use-context-tutorial

```

open it in your text editor.

```bash
code .

```

make sure that you have the react boiler plate by starting the app.

```bash
npm start

```

after you have verified that everything is working by a the react logo appearing. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c5qnbnepvc0mur9zpogo.png)

__in your src folder__ make another folder called providers 

you can do this by right clicking the src if you are using vscode then click the new folder option. 

inside the providers folder make an new __file__ called ThemeProvider.js

in your ThemeProvider.js you are going to make an exported const containing the react context object and the ThemeProvider function so that we can start declaring theme as a piece of state. 

start by importing react at the top of the file. 

```javascript
import React from 'react';

```

then make make a variable for the context to live and make it equal to React.createContext() by adding this line. 

```javascript
export const themeContext = React.createContext()

```

Now make a function that we can have state and put the themeContext.Provider with value object in the return for the ThemeProvider function. 

we are going to need props for the ThemeProvider as well.

you should have a function that looks like this. 

```javascript
const ThemeProvider = (props) => {
  return (
    <themeContext.Provider value={{

    }}>
      
    </themeContext.Provider>
  );
};

export default ThemeProvider;

```

notice that the value prop on the Provider has 2 sets of curly brackets. this is because you are breaking out of JSX for the first, then going into object notation for the second. 

between the opening and closing brackets for the Provider we are going to add the consumer

we need to add state to this function so this is a perfect job for useState.

import useState at the top. 

```javascript
import React, {useState} from 'react';

```
now add the state for the theme and set the initial state to 'light'

```javascript
const [theme, setTheme] = useState('light')

```

add the theme inside of the value for the Provider. 

Between the opening and closing angle brackets on the Provider, add the props.children object inside curly brackets. 


the whole file should look like this. 

```javascript
import React, {useState} from 'react';

export const themeContext = React.createContext()

const ThemeProvider = (props) => {
  const [theme, setTheme] = useState('light')

  return (

    <themeContext.Provider value={{
      theme
    }}>
      {props.children}
    </themeContext.Provider>
  );
};

export default ThemeProvider;

```

notice that even though we put the theme inside of an object this will still be valid javascript. this is because it is considered an [object literal](https://www.dyn-web.com/tutorials/object-literal/)

we are done in this file. Go to the index.js file so that we can wrap the app component with the provider. 

first import the ThemeProvider like this. 

```javascript

import ThemeProvider from './providers/ThemeProvider'
```

then make an app sandwich with some ThemeProvider bread like this. 

```javascript
ReactDOM.render(
  <ThemeProvider>
    <App />
  </ThemeProvider>

, document.getElementById('root'));

```

now everything inside of your application should have access to your context. 

to test it out, go to your App.js and set up the theme. 

first we need to import the useContext hook inside the App.js

```javascript
import React, {useContext} from 'react';

```

we also want the theme context in this component. 

```javascript
import { themeContext } from './providers/ThemeProvider';

```

between the lines for function App() and return we want to grab the theme with the useContext hook.

```javascript
  const {theme} = useContext(themeContext)
```

now add a console.log for the theme 


```javascript
console.log('theme', theme)
```

if your local server is still on and you did everything correctly, when you open your dev tools you should see something like this...


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bgi753pvznyqhytach67.png)

just to be sure here is the whole App.js 


```javascript

import React, {useContext} from 'react';
import logo from './logo.svg';
import './App.css';
import { themeContext } from './providers/ThemeProvider';

function App() {

  const {theme} = useContext(themeContext)

  console.log('theme', theme)


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;


```

now we can change our theme with click events. 

to do that go back to your themeProvider and add setTheme to your Providers value object the same way you added the theme.


```javascript
return (
    <themeContext.Provider value={{
      theme,
      setTheme
    }}>
      {props.children}
    </themeContext.Provider>
  );

```

don't forget the comma. ,,,

in the App.js add the setTheme inside the curly brackets to add it to the available objects from the themeContext. 

```javascript
const {theme, setTheme} = useContext(themeContext)

```
_grabbing things from themeContext_


make a button under the learn react link.

```javascript
 <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <button >change theme</button>

```

now we can make a new string populate the theme state in the ThemeProvider _from_ the App.js. 

to do this, add an onClick event with the setTheme making the new string 'dark'.

```javascript
<button onClick={() => setTheme('dark')}>change theme</button>

```

you could change theme to a boolean to make it so that you can switch back and forth but that is a challenge I leave up to you.

now we can add inline style to make the background color change on the click event.

on the div right below the return add this style attribute. 

```javascript
<div style={theme === 'dark' ? {backgroundColor: "#000000"} : null} >

```

it still doesnt work when you click it. 

there is css over riding your styles from the header attribute. 

delete the className on the header to solve the problem. 


```html
  <header>

```

everything should be working and I know you can make it prettier that I have here but the main point was to learn about context. 

You can really make this your own from here. 


see the github