Use of useReducer to manage state in React 💪
Tags: react
Published: 2019-10-26 22:42:44


I will show you in this post my experience in React with the use of `useReducer`. I hope it helps you in your work and learning.
Let's say we have a component like this:
```javascript
import React from 'react'
import {Div} from './styled'

export default
({state,dispatch})=>
{
  const el=
  <Div>
    {/*component stuff go inside here*/}
  </Div>
  return el
}
```
Folder structure of our app would be as follows:
--|myapp
&nbsp;&nbsp;&nbsp;&nbsp;--|src
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|comps
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|comp1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|index.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|styled.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|state.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|reducer.js
So we have already seen *index.js* definition. Now let's see how *styled.js* looks like:
```javascript
import styled from 'styled-components'
export const Div=
styled.div
`
/*all css for our component goes here*/
`
```
As you can see we use *styled-components* library.
*reducer.js* would be as follows:
```javascript
export default
(val={},act)=>
{
  switch(act.type)
  {
    case 'COMP1_SOMETHING':
      val=
      {
        ...val,
        any:act.val
      }
      return val
    default:
      return val
  }
}
```
We have a typical reducer function where we receive an action and give the next state. It's important to note the `act.type` value which is `COMP1_SOMETHING`. That's it, all `type`s values must begin with the component name we are defining.
Now let's see *state.js* definition:
```javascript
export default
{
  //object definition goes in here
}
```
Now let's say we have our *app* component. We are lifting state up to the *app* component. In our *app* component we will have the same file structure definition:
--|myapp
&nbsp;&nbsp;&nbsp;&nbsp;--|src
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|comps
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|app
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|index.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|styled.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|state.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|reducer.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|comp1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|index.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|styled.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|state.js
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--|reducer.js
Let's see *index.js* for the *app* component:
```javascript
import React,{useReducer} from 'react'
import {Div} from './styled'
import initialState from './state'
import reducer from './reducer'
import Comp1 from '../comp1/index'

export default
()=>
{
  const [state1,dispatch1]=useReducer(reducer,initialState)
  const [state2,dispatch2]=useReducer(reducer,initialState)
  const [state3,dispatch3]=useReducer(reducer,initialState)
  const [state4,dispatch4]=useReducer(reducer,initialState)
  const el=
  <Div>
    <Comp1 state={state1} dispatch={dispatch1}/>
    <Comp1 state={state2} dispatch={dispatch2}/>
    <Comp1 state={state3} dispatch={dispatch3}/>
    <Comp1 state={state4} dispatch={dispatch4}/>
  </Div>
  return el
}
```
As we can see we use four times the *Comp1* component. So we need to use `useReducer` four times too in order each of the *Comp1* instances have its own state.
Now let's see *state.js* definition for the *app* component. It is like this:
```javascript
import comp1 from '../comp1/state'

export default
{
  comp1
}
```
And see also *reducer.js* for the *app* component. It is like this:
```javascript
import combine from '../../redux/combineReducers'
import comp1 from '../comp1/reducer'

export default
combine
(
  {
    comp1
  }
)
```
The *styled.js* file will be the same as in the *comp1* case, only changing *CSS* inside definition.
It left us define *myapp/src/redux/combineReducers.js* which is like this:
```javascript
export default
reducers=>(val={},act)=>
{
  const nextVal = {}
  const keys = Object.keys(reducers)
  for(let i= 0; i< keys.length; i++)
  {
    nextVal[keys[i]]= reducers[keys[i]](val[keys[i]], act)
  }
  return nextVal
}
```
With these structure we can manage our state through the use of `useReducer`. To fullfill the example let's see again our *myapp/src/comps/comp1/index.js* file definition:
```javascript
import React from 'react'
import {Div} from './styled'
import Something from '../something/index'

export default
({state,dispatch})=>
{
  const toggleSomething=
  e=>
  dispatch({type:'COMP1_TOGGLE_SOMETHING'})
  const el=
  <Div>
    {
      state.comp1.showSomething&& <Something/>
    }
    <button onClick={toggleSomething}></button>
  </Div>
  return el
}
```
And in our *myapp/src/comps/comp1/reducer.js* file we have:
```javascript
export default
(val={},act)=>
{
  switch(act.type)
  {
    case 'COMP1_SOMETHING':
      val=
      {
        ...val,
        any:act.val
      }
      return val
    case 'COMP1_TOGGLE_SOMETHING':
      val=
      {
        ...val,
        showSomething:!val.showSomething
      }
      return val
    default:
      return val
  }
}
```
etc.
As you can see manage state with `useReducer` is easy. Key points are *combineReducers.js* definition and follow always the same structure which I have shown you here.
Let's say we want to define state and reducer also at the *app* level. We do it like this. In the *myapp/src/comps/app/state.js* file:
```javascript
import comp1 from '../comp1/state'

const app=
{
  //state definition for app component
}

export default
{
  comp1,
  app
}
```
And also we need the reducer definition for the *app* component which we define in the *myapp/src/comps/app/reducer.js* file:
```javascript
import combine from '../../redux/combineReducers'
import comp1 from '../comp1/reducer'

const app=
(val={},act)=>
{
  switch(act.type)
  {
    case 'APP_SOMETHING':
      val=
      {
        ...val,
        any:act.val
      }
      return val
    default:
      return val
  }
}

export default
combine
(
  {
    comp1,
    app
  }
)
```
If we want to access the state for *app* component in the *myapp/src/comps/app/index.js* file we do it by typing `state1.app.something` for example and so on (the same we did in the *comp1* *index* file definition).

We have had to use four times `useReducer` because we had four instances of *comp1* in the *app* component. We can then use `state1` and `dispatch1` resulting from the first call to `useReducer` to manage state of *app* component although `state2` and `state3` and `state4` would be valid choices too (always together with its corresponding `dispatch` function). All of them (`state` objects) have the same structure, that's it:
```javascript
{
  comp1:
  {
    //comp1 object state definition
  },
  app:
  {
    //app object state definition
  }
  //other comps definitions
}
```
I hope this article has helped you in learning and understanding.
Thank you.