A Redux reducer/middleware for managing asynchronous and operational states.
Getting Started
You can either install the module via npm
or yarn
:
npm install redux-ops --save
yarn add redux-ops
Motivation
Maintaining asynchronous and operational states is an integral part of almost every modern (web) app, but an often discussed topic when it comes to their implementation and the Redux state structure to store them accordingly.
redux-ops
is trying to take this concern away by providing a reducer, an optional middleware with action creator Blueprints, actions, selectors and utilities to
- maintain aforementioned states in a more consistent way (e.g. requests, transaction-like processes),
- communicate these async/operational state transitions,
- prevent cluttering of state slices with individual sub-states
- and to have a centralized place to store them.
Examples
Introduction: Operations
At its core, redux-ops
consists of a reducer with a set of actions for the creation, update and deletion of Operations.
An Operation represents any async or operational task in the form of the following object that gets updated and persisted within the opsReducer
.
id: '74168d' status: 'success' data: "id": 1 "name": "Jurassic World"
In the following example, we are going to fetch some movie data from a server and use these core actions to perform the state transitions.
;; // Create store and set up the reducerconst store = ;
// Create an Operation in its default stateconst opId = '74168d';; // State => { ops: { id: '74168d', status: 'started' } }
// Fetch movies and update the previously created Operation ; // State => { ops: { id: '74168d', status: 'success', data: {...} } }
A set of selectors and utility functions allows to, for example, retrieve the current state of an Operation, or clean it up when it's no longer needed.
// Get the Operation state by using one of the provided selectorsconsole; // Op => { id: '74168d', status: 'success', data: {...} }
// Delete the Operation; // State => { ops: {} }
Blueprints & Middleware
redux-ops
also comes with an optional middleware that enables the usage of so-called action Blueprints to reduce boilerplate by either using already defined action creators like the ones in the example below or by solely relying on the built-in Operations.
;; // Set up reducer and apply the middlewareconst store =
// We can either create/use existing actions (recommended), or let the Blueprints handle it for us.const fetchMovies = type: movieFetcherSTART ;const didFetchMovies = type: movieFetcherSUCCESS payload: movies ;
The createBlueprint
function wraps our action creators into actions that will be processed by the middleware.
Since we already have two designated action creators to initiate (fetchMovies
) and complete (didFetchMovies
) the Operation, we can leverage them, or let the auto-generated action creators handle non-defined cases such as the error
one, which we decided to not define for now.
; // Create a new Blueprint for managing stateconst movieFetcher = ;
When creating a new Blueprint, an id
/action type needs to be passed in. This identifier can be a string
or number
and is, amongst other use cases, also utilized for other concepts such as Operation broadcasting and unique Operations.
To kick-off the Operation, we need to dispatch the movieFetcher.start()
action.
;
The middleware will process the Blueprint-Action, start a new Operation with the id FETCH_MOVIES
(which can be chosen arbitrarily and is not directly related to existing types) and additionally dispatch the original fetchMovies()
action.
The request itself can then be sent in whatever way you prefer.
// Fetch movies and update the previously started Operation
// Get the Operation state by using one of the provided selectorsconsole;
// Delete the Operation if needed;
Documentation
License
MIT