redux-procedures
Redux procedures simplify boilerplate for side-effect routines while maintaining the flexibility of redux-sagas or redux-observables (both fully compartible)
why another lib?
I have been successfully using redux-observables and redux-sagas, but mostly the boilerplate required for them is too large for a simple side-effect.
Another brick of the inspiration was the redux-saga-routines
library, which made it really easy to work with
So the fruit of the idea of combining Promise and routines model is this library.
usage
Create a auth.dux.js - is a login reducer file following Ducks convention:
const loginRequest = (payload, meta, storeInstance) => axios.post('/login', payload);
const LoginProcedure = createProcedure('LOGIN', loginRequest);
export default (state = {
isAuthenticated: false,
authenticating: false,
user: false
}, action) => {
switch (action.type) {
case LoginProcedure.TRIGGER:
return ({
...state,
authenticating: true,
});
case LoginProcedure.SUCCESS:
return ({
...state,
isAuthenticated: true,
user: action.payload.user
});
case LoginProcedure.FAILURE:
return ({
...state,
isAuthenticated: false,
error: action.payload
});
case LoginProcedure.FULFILL:
return ({
...state,
authenticating: false,
});
default:
return state;
}
}
Add initialization to your store:
import { procedureMiddleware } from 'redux-procedures';
const middlewares = [
/* epicMiddleware,
sagaMiddleware,
yourOtherMiddlewares, */
procedureMiddleware
];
const store_enhancers = [
applyMiddleware(...middlewares)
];
const store = createStore(
baseReducer,
initial_state,
composeEnhancers(...store_enhancers)
);
Use your routine:
const payload = { username, password };
const meta = { metaValue: 'value' };
LoginProcedure(payload, meta)
.then(result => { console.log(result) })
.catch(error => { console.error(error); })
Await an action
How to pause promise execution until an action arrives:
import { ActionPromise } from 'redux-procedures';
ActionPromise('ACTION_TYPE')
.then(action => {
console.log('action has been dispatched', action);
});
redux-saga and redux-observables integration
If you need to use complex logic, just dispatch an awaited action:
// your saga
function * () {
const r = yield race({
t: take('SOME_CONDITION_ACTION'),
p: call(someApi)
});
// the condition is met, so we are ok to dispatch
dispatch('CONTINUE_THE_PROCEDURE');
}
// your procedure
import { ActionPromise } from 'redux-procedures';
ActionPromise('CONTINUE_THE_PROCEDURE')
.then(action => {
console.log('action has been dispatched', action);
});