Context API and useContext
Tags: webdev, javascript, programming, react
Published: 2023-04-09 13:00:00

_Props_ help you pass down data from parent to child components. By so doing, it's using the flow system of data passage (_top to bottom_) to get that done. However, when the project grows, it becomes more complex using _props_ to pass down data from one component to another that is not directly a child of it, or where the said component is deeply nested in the application. 

Sometimes, the components in-between the parent and the child component may not need this information but they are obliged to pass it down until it gets to the component that needs it. This can be a heck of a problem and this is where you need the  _**ContextAPI()**_.

## What is ContextAPI

The ContextAPI helps you pass _props_ or _state_ through the component tree without having to do it manually. It helps you pass information from the parent component to several other components in the application no matter how deeply nested they are. With _useContext_, the information tunnels through from the parent component to the component that needs it through the use of context. It helps solve the _prop drilling_ problem encountered in React state management.

Some types of data are too complex to be shared through props. Data such as _Auth_ and _theme_ can be passed through _context_ without compromising your application. 
_ContextAPI_ is an in-built React library so you don't need to bother about increasing your build size or having to install a third-party library.

With _useContext_, any component that needs information or prop from the parent component can easily ask for it and have access to it right away with the use of _context_. 

## Prop-Drilling

Prop-drilling is the process of passing props from a parent component down to child components no matter how deeply nested they are. The passing of data is done manually from component to component until the desired component is reached. 

Below is a diagram and an example of prop-drilling. 


![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wrc563fwlqu9kvnxkw8x.png)

In this diagram, the PARENT component (APP) is to pass state around down to as far as PLAYERIDENTITY component. Even though the DASHBOARD component doesn't have a need for this state, the data had to pass through it to get to the other children components: PLAYERSTATE and PLAYER. PLAYERSTATE consumed its share of state; _activeplayer_ and PLAYER component passed on the state to PLAYERSEX and PLAYERNAME even though it didn't have any use for them. PLAYERSEX received the _sex_ of the player and outputted it, and PLAYERNAME sent the last prop down to PLAYERIDENTITY.  

Let's see this diagram in code, so you get to understand prop-drilling better. 

```
import { useState } from 'react'
import './App.css'
import Dashboard from './Dashboard'

function App() {

    const [sex, setSex] = useState('male')
    const [name, setName] = useState('Louisa')
    const [activePlayer, setActivePlayer] = useState('Yes')

  return (
      <div className="App">
          <h3> Welcome {name}</h3>
          <Dashboard {...{sex, name, activePlayer}} />
    </div>
  )
}

export default App
```

```
import React from 'react'
import PlayerState from './PlayerState'
import Player from './Player'

const Dashboard = ({sex, name, activePlayer}) => {
    return (
        <div>
            <PlayerState {...{ activePlayer }} />
            <Player {...{ sex, name }} />
        </div>
  )
}

export default Dashboard
```

```
import React from 'react'

const PlayerState = ({activePlayer}) => {
  return (
      <div className='player-state'>
          <h4>Is the player active? { activePlayer}</h4>
      </div>
  )
}

export default PlayerState
```

```
import React from 'react'
import PlayerSex from './PlayerSex'
import Playername from './Playername'

const Player = ({sex, name}) => {
  return (
      <div className='player'>
          <PlayerSex {...{ sex }} />
          <Playername {...{ name }} />
    </div>
  )
}

export default Player
```

```
import React from 'react'

const PlayerSex = ({sex}) => {
  return (
      <div>Can you guess player sex? { sex}</div>
  )
}

export default PlayerSex
```

```
import React from 'react'
import PlayerIdentity from './PlayerIdentity'

const Playername = ({name}) => {
  return (
      <div>
          <h3>Just one more chance to guess player name right</h3>
          <PlayerIdentity {...{ name }} />
        </div>
  )
}

export default Playername
```

```
import React from 'react'

const PlayerIdentity = ({name}) => {
  return (
      <div>{ name}</div>
  )
}

export default PlayerIdentity
```
This process can be tedious and any slight change of code or correction can break the application. Also, it is prone to errors such as a typo which can ruin the whole process.

With _context_, a lot of this stress can be done away with. Let's see how _useContext_ works.

## The 3 Stages of useContext

There are three (3) stages of _useContext_.

1. _**createContex**t_: This is the stage where the _context_ is created using the _createContext()_ function. It receives only one argument called _defaultValue_.

2. **_Provider_**: This is a component of the _context_. It is used to wrap all the components that need access to the information in the context. It receives a single _prop_ called _value_. The value prop contains the value of your context (sounds like a tautology, but you will see what I mean later). All the components wrapped with the provider, and their children all have access to the value prop of the context.

3. Consumer: This is another component of the _context_. It is used to wrap the components that will have access to the components. When the _Consumer_ is wrapped around a component, the value of the state can change, but when it's not, the value of the state remains the _defaultValue_.

## How to use Context

To use context, you have to create it with an _in-built function_ in the _useContext_ hook called _createContext_. Now, let's create our context, and we will be using the same example we used in the _prop-drilling_ example but now using the useContext concept. 

```
import React, { createContext } from 'react'

export const MyContext = createContext();
```

Now, this is the first stage of the solution of our code. Next, we will wrap our _App_ component with the _context_ we just created.

```
import { useContext, useState } from 'react'
import './App.css'
import Dashboard from './Dashboard'
import { MyContext } from './Context'

function App() {

     const [sex, setSex] = useState('male')
     const [name, setName] = useState('Louisa')
     const [activePlayer, setActivePlayer] = useState('Yes')   

  return (
      <div className="App">
          <MyContext.Provider value={{
              sex, setSex, name, setName, activePlayer, setActivePlayer
          }}>
              <h3> Welcome {name}</h3>
                <Dashboard />
          </MyContext.Provider>
         
    </div>
  )
}

export default App
```
 
As you can see, we wrapped the _App_ being the parent component with our context _MyContext.Provider_. With this, all the components in the application have access to the _value_ prop we set.

Now, let's see the rest of the code. You will realize they aren't as large as they were while _prop-drilling_. Now, they are lightweight and much more readable while still giving the same result.

```
import React, { useContext } from 'react'
import { MyContext } from './Context'

const PlayerState = () => {
    
    const playerStatus = useContext(MyContext)

  return (
      <div className='player-state'>
          <h4>Is the player active? { playerStatus.activePlayer}</h4>
      </div>
  )
}

export default PlayerState

```

```
import React, { useContext } from 'react'
import { MyContext } from './Context'

const PlayerSex = () => {
    
    const playerSex = useContext(MyContext)

  return (
      <div>Can you guess player sex? { playerSex.sex}</div>
  )
}

export default PlayerSex
```

```
import React, { useContext } from 'react'
import { MyContext } from './Context'

const PlayerState = ({ activePlayer }) => {
    
    const playerStatus = useContext(MyContext)

  return (
      <div className='player-state'>
          <h4>Is the player active? { playerStatus.activePlayer}</h4>
      </div>
  )
}

export default PlayerState
```

To be able to output our JSX, we first name a variable, then call our _context_ using the _useContex_t hook. Then we can render using our variable and call on the state.

Now, these are all the components we need because we didn't have to pass the _props_ through every component manually to get to our desired component. 

If this was helpful, do well to follow me. And if you have questions, hola at me in the comment section.

Have a great weekend my friends.