Middlewares with react context and hooks
Tags: javascript, react, middleware, hooks
Published: 2019-10-07 07:32:11

Continuing the idea explored in the [previous article](https://dev.to/vanderleisilva/global-state-management-with-react-hooks-and-context-5f6h) of having a global state management using pure react (with react context and hooks), we’re going to explore now how to take advantage of the middlewares concept, implementing for that a loger and localStorage middleware to our todo app, [check here the live demo](https://vanderleisilva.github.io/react-context/) and [here the source code](https://github.com/vanderleisilva/react-context/tree/middlewares)

### About middlewares

The term can slightly differ from each depending on the middleware type (*Database Middleware, Integration Middleware, Application Middleware, Object Middleware, Remote Procedure Call (RPC) Middleware, Message Oriented Middleware ...*) but essentially they have the idea of a composable peace of code running in the middle of to distincts processes improving their communication, and by process we could use more specific terms according to the scenario that we are talking about. 

In the web development niche this term is spreedly used in server side technologies such as [Laravel](https://laravel.com/docs/6.x/middleware), [ExpressJS](http://expressjs.com/en/guide/using-middleware.html), [nestJS](https://docs.nestjs.com/middleware) among others as: 

> A composition of functions that are called, in a given order, before the route handler and that usually each one of them have access to the request information and a reference to the next function in this chain

This idea was taken by the front-end fellows, mainly applied by the state management libraries: [redux](https://redux.js.org/advanced/middleware), [mobx](https://github.com/mobxjs/mobx-state-tree/blob/master/docs/middleware.md), [vuex](https://vuex.vuejs.org/guide/plugins.html) (the last even though with a different nomenclature “plugin” the idea is the same), and what they all do is to provide a way of running some code between dispatching an action, and the moment it changes the application state.

Of course this concept can be used in other scenarios, this [article](https://medium.com/@burimshala/how-to-implement-middleware-in-angular-using-ui-router-b3267dddbae8) explores its usage attached to the router change in angular, getting closer to the above mentioned server-side ones. But for now we’re going to explore the first one.

### Show me the code

```javascript
import { initial, final } from './log';
import localStorage from './localStorage';
 
export default ({ state, action, handler }) => {
  const chain = [initial, handler, localStorage, final];
 
  return chain.reduce((st, fn) => fn(st, action), state);
};
```

That’s all what matters, we need a function to create a middleware chain and execute all them in a given order and of course call our handler (the reducer function called by a given action in our application).

```javascript
const chain = [initial, handler, localStorage, final]
```

Here we define the middlewares that will be called and in which order they will, the ones that comes before **handler** are the pre-middlewares (you put here all middlewares that you want to run something before the state have changed) and the others the post-middlewares (the ones that execute something with the new state).

The middleware function signature follows the same pattern of the reducers:

```javascript
(state, action) => newState
```

As an example here is the initial log middlewares:

```javascript
const initial = (state, action) => {
  console.log(action);
  console.log(state);
  return state;
};
```

The middleware just log the initial state (before the state have being change by the reducer) on the console.

Here we have a more interesting one:

```javascript
import store from 'store2';
 
export default state => {
  store.set(state.storeId, state);
  return state;
};
```

This middleware saves the current state on the local storage, I’m using for this a small library [store2](https://www.npmjs.com/package/store2) just to make sure retrocompatibility with old browsers and also avoiding working with try catch statements.

I have on the app state an storeId property with the name of the key that will be saved on the local storage, so basically in this call:

```javascript
store.set(state.storeId, state);
```

I store in the given key the given state. If you [check the app again](https://vanderleisilva.github.io/react-context/), play around and refresh the page, the information will still be there.

And lastly we have:  

```javascript
return chain.reduce((st, fn) => fn(st, action), state);
```

We use the [reduce array method](https://www.w3schools.com/jsref/jsref_reduce.asp) to iterate over each item of the chain getting the result of the previous and passing to the next item.

### There it is
We have now returned to the basics and explored how the main state management libraries conceptually work with middlewares, giving us the same results with less dependencies and less complexity. We now understand what happens, instead of just blindly using them.

What do we got from it!? A better reasoning of when to use these state libraries.

What do we go from now!? More hooks on the way, check here the new custom hooks from react-router-v5.1 and see you soon. ;)


##### References
https://dev.to/vanderleisilva/global-state-management-with-react-hooks-and-context-5f6h
https://vanderleisilva.github.io/react-context/
https://laravel.com/docs/6.x/middleware
http://expressjs.com/en/guide/using-middleware.html
https://docs.nestjs.com/middleware
https://redux.js.org/advanced/middleware
https://github.com/mobxjs/mobx-state-tree/blob/master/docs/middleware.md
https://vuex.vuejs.org/guide/plugins.html
https://www.w3schools.com/jsref/jsref_reduce.asp
https://reacttraining.com/blog/react-router-v5-1/