Global State Management with React usestate, useContext Hooks and Context API.
Tags: react, contextapi, reactcreatecontext, statemangement
Published: 2019-08-21 07:30:04

---
title: Global State Management with React usestate, useContext Hooks and Context API.
published: true
tags: React,Context Api,React CreateContext,State Mangement
canonical_url: https://milddev.com/react/react-createcontext/
---

 ![State Management with React createContext](https://milddev.com/wp-content/uploads/2019/08/state-management-300x157.jpg)

It’s been quite a while since react has announced a stable version of context API in its 16.3.0 release. Before that libraries like Redux, MobX were to be used for state management. In this post I will explain with some examples on how we can manage the state of the components by using context API and Hooks.

Let’s start with a very simple scenario like this:

![](https://milddev.com/wp-content/uploads/2019/08/context-simple-scenario.jpg)<figcaption>A simple use case of context API</figcaption>

We Have a Basecomponent with a child named ChildComponentA which further has its own Child named ChildComponentB. Now we want to pass a const from our BaseComponent to ChildComponentB, we can do this easily by passing the const as prop from our BaseComponent to ChildComponentA and then to ChildComponentB it may seem right to you but there is a problem, what if we have 10 child components between BaseComponent and ChildComponentB. Well we must drill down the prop all the way from BaseComponent through all the child components until we reach ChildComponentB. This is obviously not the right way, to avoid this problem we use Context API.

## How does Context API work?

The way Context API work is that we create a context using React.createContext() and provide it at the top of our components tree by using a \<Context.provider\> once we have provided the context at the top of our components tree it is accessible at every level inside that tree. We can then consume its value with \<Context.consumer\> or useContext hook. It may sound complicated, but you will find it simple as you will see the examples below.

## Example 1 (Consume the value of context)

This example is for the above scenario with three components.

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

const FruitContext = React.createContext()

const BaseComponent = () => {
  return (
    <FruitContext.Provider value={'Apple'}>
        <ChildComponentA />
    </FruitContext.Provider>
  )
}

const ChildComponentA = () => {
  return (
    <div>
      <ChildComponentB />
    </div>
  )
}

const ChildComponentB = () => {
  const fruitName = useContext(FruitContext)

  return (
    <h1>
      {fruitName}
    </h1>
  )
}

export { BaseComponent }
```

Instead of using \<Context.consumer\> we can also use useContext hook like this.

```javascript
const ChildComponentB = () => {
  const fruitName = useContext(Context)

  return (
    <h1>{fruitName}</h1>
  )
}
```

Example 2 (Consuming Multiple Contexts)

This example is like the previous one except for the fact that we are consuming multiple contexts instead of a single context. In our BaseComponent we have provided the value for two contexts name and age and then we have consumed those values in the ChildComponentB like we did previously.

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

const Name = React.createContext()
const Age = React.createContext()

const BaseComponent = () => {
  return (
    <Name.Provider value={'Mateen'}>
      <Age.Provider value={'20'}>
        <ChildComponentA />
      </Age.Provider>
    </Name.Provider>
  )
}

const ChildComponentA = () => {
  return (
    <div>
      <ChildComponentB />
    </div>
  )
}

const ChildComponentB = () => {
  const name = useContext(Name)
  const age = useContext(Age)

  return (
    <h1>
      I am {name} and I am {age} years old.
    </h1>
  )
}

export { BaseComponent }
```

## Example 3 (Context API with useState hook)

You should be thinking we haven’t done any state management, well in this example we will combine Context API with useState hook to manage the state of our App. Now whenever the value of our context is updated every component that uses it will also get re rendered to sync the state of all the components. If you are not familiar with the useState hook, consider this example:

```javascript
Const [state, setState] = useState(‘initial value’)
```

> State is the variable that is been assigned the value “initial State” and setState is a callback function to update the value of our state variable. To update the value of our state variable we must call setState and whenever the value of state variable changes every component that uses it re renders. This is enough for now to understand this useState hook.
> 
> <cite>useState() hook</cite>

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

const Theme = React.createContext()

const BaseComponent = () => {
  const [theme, setTheme] = useState('Light')

  const toggleTheme = () => {
    setTheme(theme === 'Light' ? 'Dark' : 'Light')
  }

  return (
    <Theme.Provider value={theme}>
      <ChildComponentA />
      <button onClick={toggleTheme}>Change Theme</button>
    </Theme.Provider>
  )
}

const ChildComponentA = () => {
  return (
    <div>
      <ChildComponentB />
    </div>
  )
}

const ChildComponentB = () => {
  const theme = useContext(Theme)

  return (
    <h1>
      current theme is {theme}.
      </h1>
    )
}

export { BaseComponent }
```

To know more about theming in react see [this](https://milddev.com/react/set-up-light-and-dark-theme-in-react/) post.

## Example 4 (Global state Management by passing callback functions as the context value)

This example is a little complicated as it falls in the category of global state management. One of the easiest ways to manage the state of a component globally (To update the state of a component from anywhere inside the provider) is to pass the callback function as the context value so we can call it anywhere we want to update our state variables. In this example we have a list of movies with movie name and director Name we can add more movies to the list, get the number of movies in the list and every time we add a movie to the list our component updates the UI.

Movie Provider holds the initial list and as we wrap our components with this provider, we can access and update the list of movies. Header component displays the number of movies in our list. Add Movie component adds the movie to the list using a form. Movies component displays the list of the Movies in the UI.

#### MovieProvider.js

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

export const MovieContext = React.createContext();

export const MovieProvider = (props) => {
  const [movies, setMovies] = useState([
    {
      name: 'Wreck it Ralph',
      director: 'Rich Moore',
      id: 432
    },
    {
      name: 'The Incredibles',
      director: 'Brad Bird',
      id: 234
    },
    {
      name: 'Despicable me',
      director: 'Pierre Coffin',
      id: 542
    }
  ])

  return (
    <MovieContext.Provider value={[movies, setMovies]} >
      {props.children}
    </MovieContext.Provider>
  )

}
```

#### AddMovie.js

```javascript
import React, { useContext, useState } from 'react'
import { MovieContext } from './MovieProvider'

const AddMovie = () => {
  const [movies, setMovies] = useContext(MovieContext)

  const [movieName, setMovieName] = useState('')
  const [directorName, setDirectorName] = useState('')

  const handleSubmit = event => {
    event.preventDefault()
    const rand = Math.random()
    setMovies(movies => [
      ...movies,
      { name: movieName, director: directorName }
    ])
  }

  return (
    <form onSubmit={handleSubmit} style={{ padding: '10px' }}>
      <input
        type='text'
        value={movieName}
        placeholder='Enter Movie Name'
        onChange={e => setMovieName(e.target.value)}
      />
      <input
        type='text'
        value={directorName}
        placeholder='Enter Director Name'
        onChange={e => setDirectorName(e.target.value)}
      />
      <input type='submit' value='Add Movie' />
    </form>
  )
}

export default AddMovie
```

#### Header.js

```javascript
import React, { useContext } from 'react'
import { MovieContext } from './MovieProvider'

const Header = () => {

  const header = {
    paddingLeft: '15px',
    backgroundColor: 'blue',
    color: 'white',
    fontStyle: 'light',
    width: '100%',
    height: '50px',
  }

  const [movies] = useContext(MovieContext)

  return (
    <div style={header}>
      <h1>Number of movies {movies.length}</h1>
    </div>
  )
}

export default Header
```

#### Movies.js

```javascript
import React, { useContext } from 'react'
import { MovieContext } from './MovieProvider'

const Movies = () => {
  const [movies] = useContext(MovieContext)

  return (
    <div>
      {movies.map(movie => (
        <div key={movie.id} style={{padding:'10px'}}>
          Movie Name:{' '}
          <span style={{ color: 'red', fontStyle: 'italic' }}>
            {movie.name}
          </span>{' '}
          | Director Name{' '}
          <span style={{ color: 'red', fontStyle: 'italic' }}>
            {movie.director}
          </span>
        </div>
      ))}
    </div>
  )
}

export default Movies
```

#### App.js

```javascript
import React from 'react'
import {MovieProvider} from './components/MovieProvider'
import Header from './components/Header';
import Movies from './components/Movies'
import AddMovie from './components/AddMovie'

function App() {
  return (
    <MovieProvider>
      <Header />
      <AddMovie />
      <Movies />
    </MovieProvider>
  )
}

export default App
```

This is How the final output looks like:

![](https://milddev.com/wp-content/uploads/2019/08/state-management-react-create-context.png)<figcaption>Final output</figcaption>

The post [State Management with Context Api, UseState and useContext hooks – React CreateContext.](https://milddev.com/react/react-createcontext/) appeared first on [Mild Dev](https://milddev.com).

Don't forget to like, share and follow as it helps a lot. If you have any question let me know in the comments section.