Using useContext and useState hooks as a store
Tags: react, context, store, state
Published: 2019-07-06 05:26:01

---
title: Using useContext and useState hooks as a store
published: true
description: For small to medium Apps, we don't necessarily need to use Redux!
tags: React JS, context, store, state
---

I built a small internal company app (_Stand Up Bot_) that we note down our _what's new_, if there was anyone that needs any help and our _pairing configs_ (we practice pair programming) for the day. In this app, I wanted to pass the notes data from the input component to the publish module that sends to our Discord channel as a post (thus the name _Stand Up Bot_).

The usual practice is to use a _state container_ such as redux to manage the passing of data between components, but using Redux requires a deep understanding of `reducers` and `actions` that is not really necessarily if your _small_ app simply wants to pass data without mutating it.

React JS provides us an api called `createContext` which we can easily call any data from any component of your app. Usually when a value is needed to be used in a child component from a parent component, we would usually pass the data down as a `prop`. Sometimes a `prop` is passed down to a child component of another child component of another child component of a parent! This is what we call _prop drilling_.

In this post, I will share what I've learned and how i tackled my problem by using the useContext Hooks. I enjoyed using it and hope you will too!

## React Context

> Context provides a way to pass data through the component tree without having to pass props down manually at every level.
>
> - [Official React JS Website (Context)](https://reactjs.org/docs/context.html)

I have 3 sets of data that I want to pass to the input component and store it globally so that it is easily accessible.

```javascript
const teamMembersNames = ['John', 'Mary', 'Jason', 'David']

const [sharing, setSharing] = React.useState([])
const [help, setHelp] = React.useState([])
const [pairing, setPairing] = React.useState(teamMembersNames)
```

As per the React Official Context docs, i will need to use `createContext` and nest my main component with the `Context.Provider`.

```
<StoreContext.Provider value={store}>
  <App />
</StoreContext.Provider>
```

Then at the component, we nest the component again with a `Context.Consumer` tag.

```
<StoreContext.Consumer>
  {store => <InputComponent store={store} />}
</StoreContext.Consumer>
```

## React useContext Hooks

React `useContext` hooks provides us an elegant way to call our data without nesting. Let's try it out!

We'll move our Context provide to its own file.

```javascript
// ./src/utils/store.js
import React from 'react'

export const StoreContext = React.createContext(null)
```

In the same context file we will define a default function that the data are initialized and it's children will have data provided.

```javascript
// ./utils/store.js

import React from 'react'

export const StoreContext = React.createContext(null)

export default ({ children }) => {
  const teamMembersNames = ['John', 'Mary', 'Jason', 'David']

  const [sharing, setSharing] = React.useState([])
  const [help, setHelp] = React.useState([])
  const [pairing, setPairing] = React.useState(teamMembersNames)

  const store = {
    sharing: [sharing, setSharing],
    help: [help, setHelp],
    pairing: [pairing, setPairing],
  }

  return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
}
```

Now our Context has setup, we can wrap our context to the main app. In the `index.js` file, i will wrap the app with the Context.

```javascript
// ./index.js

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App'
import StoreProvider from './utils/store'

ReactDOM.render(
  <StoreProvider>
    <App />
  </StoreProvider>,
  document.getElementById('root')
)
```

In any component, to fetch the data, we will use useContext.

```javascript
import React from 'react'
import { StoreContext } from '../utils/store'

const SomeComponent = () => {
  // to fetch the sharing data
  const { sharing } = React.useContext(StoreContext)
}
```

Now our components in the app will be provided with the store data. But to fetch the data, lets use the `useContext` hooks instead of _Context.Consumer_ syntax.

I have created an input component that will get user input and set the state according to the type (sharing, help or pairing)

```javascript
// ./components/input-section.js

import React from 'react'
import { StoreContext } from '../utils/store'

export default ({ type, description }) => {
  const [input, setInput] = React.useState('')
  const {
    [type]: [data, setData],
  } = React.useContext(StoreContext)

  /*
  .
  . some other handlers
  .
  */

  return (
    <div>
      <ul>
        {data.map(d => (
          <li>{d}</li>
        ))}
      </ul>
      <input
        placeholder={description}
        type="text"
        value={input}
        onChange={e => setData([e, ...data])}
      />
    </div>
  )
}
```

I've shortened the component so we can see how the data were fetched. We simply call the `React.useContext(StoreContext)` and the value that was passed to the provider in the `store.js` are fetched exactly as it was passed. No props were passed to this component from the parents component!

To further clarify, in the parent component, I pass the type (sharing, help, pairing) that was the key to store datas.

```javascript
// ./app.js
import React from 'react'
import InputSection from './components/input-section'

const App = () => {
  /*
  .
  . some stuffs
  .
  */

  return (
    <InputSection type="sharing" description="What are your thoughts?..." />
  )
}
```

As you can see, I did not pass any states or data props to the child component!

Hope this helps you understand better and display how elegant using `useContext` hook is! For the full app, check out my [repo](https://github.com/nazmifeeroz/stand-up-bot).

Happy Coding!