Very simple to use middleware for redux to make side effects for actions. Inspired by redux-saga but not uses generators, instead relies on async functions and can be used with redux-thunk.
- Register middleware
import sideEffectMiddleware from '@actualwave/redux-side-effect';
const store = createStore(
myReducers,
applyMiddleware(sideEffectMiddleware),
);
- Add side effects
import { take, put, select, call } from '@actualwave/redux-side-effect';
take('FETCH_DATA', async (action) => {
const { data } = await axios.get('/something');
put({ type: 'FETCH_DATA_SUCCESS', payload: data });
});
take('POST_DATA', async (action) => {
// ....
});
take('PATCH_DATA', async (action) => {
// ....
});
That's it.
This middleware will work with single redux store, it's not a problem for most of the projects because developers usually create one redux store per application. But for projects that may be using multiple stores and this middleware, they have to generate middlewares for each store, like this:
main-redux-store.js
import { createNamespace } from '@actualwave/redux-side-effect';
const { put, call, select, take, middleware } = createNamespace();
const store = createStore(
mainReducers,
applyMiddleware(middleware),
);
export { put, call, select, take };
sub-redux-store.js
import { createNamespace } from '@actualwave/redux-side-effect';
const { put, call, select, take, middleware } = createNamespace();
const store = createStore(
subReducers,
applyMiddleware(middleware),
);
export { put, call, select, take };
With such setup you could use separate sets of functions for different stores
side-effects.js
import * as main from 'main-redux-store.js';
import * as sub from 'sub-redux-store.js';
main.take('ACTION_TYPE', () => main.put({ type: 'ACTION_SUCCESS' }))
const createSubEffect = ({ take, put }) => {
take('GENERAL_ACTION_TYPE', () => put({ type: 'GENERAL_ACTION_SUCCESS' }));
};
createSubEffect(main);
createSubEffect(sub);
An example:
import sideEffectMiddleware, { take, put, select, call } from '@actualwave/redux-side-effect';
const store = createStore(
myReducers,
compose(
applyMiddleware(thunkMiddleware, sideEffectMiddleware),
// Redux Tool Google Chrome Extension setup
window.__REDUX_DEVTOOLS_EXTENSION__
? window.__REDUX_DEVTOOLS_EXTENSION__()
: compose,
),
);
// Side effect function could be a normal function too
take('action-type', (action) => {
console.log('MY ACTION TYPE INTERCEPTED:', action);
put({ type: 'side-effect-success' });
select((store) => console.log(store));
});
take('async-action-type', async (action) => {
console.log('MY ACTION TYPE INTERCEPTED:', action);
const value = await call(myFunction, 'arg1', 'arg2', 'arg3');
await put({ type: 'side-effect-success', payload: { value } });
select((store) => console.log(store));
});