Orchestrate Actions with Redux Listeners
There are multiple ways and libraries to handle asynchronous data flows in Redux. Some do a lot, some do just a little.
redux-listeners is a small middleware for Redux which makes handling async are orchestrating action in Redux a breeze.
It’s the sweet spot in-between redux-thunk
and redux-saga
What is redux-listeners?
With redux-listeners I aim to make it easy to respond to actions being dispatched to the store without adjusting the action itself.
It allows you to listen in on action types being dispatched to the store and dispatching new actions afterwards. This way you can separate your action creators from the logic which follows the action.
The data flow can be described as such:
- Action is dispatched to the store
redux-listener
middleware sees type of action matches a registered listener- Listener is executed, which chooses to dispatch a new action to the store
- Reducers of the original action are handled
- New action will be dispatched to the store
Example usage
import { createStore, applyMiddleware } from 'redux';
import { createMiddleware } from 'redux-listeners';
// import your reducers
import rootReducer from './reducers';
// create action middleware
const listenMiddleware = createMiddleware();
const store = createStore(
rootReducer,
applyMiddleware(listenMiddleware),
);
// registering the listeners
listenMiddleware.addListener('FETCH_DATA', async (dispatch) => {
try {
const response = await fetch('/some-data');
dispatch({
type: 'FETCH_DATA_SUCCESS',
payload: await response.text(),
});
} catch (err) {
dispatch({
type: 'FETCH_DATA_FAILED',
payload: err,
})
}
});
listenMiddleware.addListener('FETCH_DATA_FAILED', (dispatch, action) => {
// display the error in console by reading the action
console.error(action.payload.message);
});
// Make the listeners start fetching data
store.dispatch({ type: 'FETCH_DATA' });
Documentation
Visit redux-listeners
on Github for a full explanation, how to install, and documentation.
Separating actions from logic
In my opinion, actions creators should only contain create action objects to be dispatched on the store. All side effects (like fetching data) should be handled elsewhere.
Most of the times you also want to keep logic like this out of your application to keep it as simple as possible and make the logic behind actions flexible and easy to replace without touching the application itself.
Possible use cases
Fetching data async is just one of the examples of how to use redux-listeners, but there are way more ways you can use and combine redux-listeners with other principles.
redux-listeners is great for handling parts of the program which live outside of the Redux cycle. You can orchestrate mutations on localStorage or other parts of the browser’s API.
Redirecting to other pages after an action is dispatched is also a use case I use myself.
Wrapping up
Use redux-listeners if you’re looking for something other then redux-thunk
, but not as complex and big as redux-saga
.