Middleware in Redux
June 27, 2020
Middleware is a "middle-man" between your store running actions and reducers changing the state. You can have more than 1 middleware in your project.
It can be used when to log whenever an action has occurred or even give crash reports. Middleware is declared in your ./src/index.js
file.
applyMiddleware
needs to be imported from redux
.
import { createStore, applyMiddleware } from 'redux';
This next snippet is from the Redux docs Opens in a new window since it's a good example. This needs to be declared before creating the store.
const logger = store => {
return next => {
return action => {
console.log('dispatching', action);
const result = next(action);
console.log('new state', store.getState());
return result;
}
}
}
There are a few things going on here:
store
is the created store being used- logs to the console what action is being dispatched
next(action)
is the same asstore.dispatch(action)
, which is dispatching the givenaction
store.getState()
returns the current state of the store and logs it to the console
applyMiddleware()
passes logger
as an argument and is the second argument in the createStore()
method.
In my Redux post , the Redux Devtools was declared as the second argument, this will be changed soon.
const store = createStore(
reducer,
applyMiddleware(logger)
);
The image below shows the 2 console messages.
There are some pre-made middlewares you can use such as redux-thunk Opens in a new window which is made for using asynchronous actions in your store.
Install:
npm install redux-thunk
Import thunk
from redux-thunk
in ./src/index.js
:
import thunk from 'redux-thunk';
Then add it to the applyMiddleware()
method.
const store = createStore(
reducer,
applyMiddleware(logger, thunk)
);
In colors.js
where the actions are declared, I renamed removeColor
to removeColorAction
and kept the same logic. Instead of a component removing a color immediately, a new created removeColorDelay
will be used to dispatch this action. Because of redux-thunk
, I can create a setTimeout
to make an asynchronous dispatch.
./src/store/actions/colors.js
const removeColorAction = (color) => {
return {
type: actionTypes.REMOVE_COLOR,
color: color
}
}
export const removeColorDelay = (color) => {
// dispatch is from redux-thunk
return dispatch => {
setTimeout(() => {
dispatch(removeColorAction(color));
}, 3000)
}
}
With a component calling removeColorDelay
, there will be a 3 sec delay before the color is removed from the state.
If using the Redux Devtools Opens in a new window , you need to change the setup when using middleware.
Import compose
from redux
.
import { createStore, applyMiddleware, compose } from 'redux';
Declare a composeEnhancers
constant which wraps the applyMiddleware()
function.
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
composeEnhancers(applyMiddleware(logger, thunk))
);
This example can be found in the redux-intro repo Opens in a new window .
Resources: