redux-echos
v0.9.3
Published
A lightweight redux middleware to decouple & serialise the dependency of states.
Downloads
9
Maintainers
Readme
redux-echos
A lightweight redux middleware to decouple and serialise state dependencies.
This sounds awful. Or a better version:
It helps to deal with the to-be-laterly-dispatched actions.
Scenarios
- state dependency
- action workflow
Examples
First of First, but not actually
Apply echos as a middleware to the redux store.
import echos from 'redux-echos'
import { createStore, applyMiddleware } from 'redux'
const store = createStore(reducer, applyMiddleware(echos))
note-1: this step may be safely skipped sometimes when redux-thunk is here and you would dispatch all echo actions manually.
note-2: If note-1 does not make clear sense for you, applying the middleware is a safer option.
Action Forking
An action, in its reducer, may spawn other action(s) now.
import { echo } from 'redux-echos'
const reducer = (state, action) => {
if (action.type === 'The/Source/ACTION') {
echo({
type: 'An/Echo/ACTION',
some: state.an.important.value
}, action)
return {...state, key: 'new-value'}
}
return state
}
And of course, the function echo() can also be called out of a reducer to queue an action.
Action Chain
Instead of emitting one or several independent actions, you can make a series of actions, which can have thunks, to be dispatched sequentially.
import { chain } from 'redux-echos'
const reducer = (state, action) => {
if (action.type === 'User/Is/AUTHENTICATED') {
chain(
NetworkActions.loadUserProfile(), action
)(
NetworkActions.loadFriendProfiles()
)
return {...state, key: 'new-value'}
}
return state
}
And if all actions in a chain are common object actions, like:
chain(A1)(A2)(A3)...
works exactly like:
echo(A1); echo(A2, A1); echo(A3, A2); ...
But if there is a thunk, e.g: A1, then A2 will only be dispatched after A1's resolved action has been dispatched.
If the resolved action is still a thunk, A2 will continue to wait recursively until a final action is dispatched.
note-1: currently, redux-echos only supports redux-thunk.
note-2: if the source action is not empty, for example:
chain(A1, A0)(A2)(A3)...
can be coded as:
import { follow } from 'redux-echos'
follow(A0)(A1)(A2)(A3) ...
since the A0 is taken as the source action, follow(...) will not try to dispatch it.
note-3: if you need more complex workflow like feature of forking & merging, please refer to redux-action-flow
Action Translating
A state may associate itself with another one which it depends on.
import { listen } from 'redux-echos'
const translator = (action, state) => ({
type: 'An/Echo/ACTION',
some: state.an.important.value
})
listen('The/Source/ACTION', translator)
or apply a selector to help the translator
const translator = (action, value) => ({
type: 'An/Echo/ACTION',
some: value
})
const selector = state => state.an.important.value
listen('The/Source/ACTION', translator, selector)
Coding Practice
- w/ or w/o redux-thunk
- reducer-centred code organising.
- analyse action flow.
API Reference
Basics
They should be enough for common scenarios.
default exports: middleware(store) => (next) => (action)
the middleware
echo(action, source)
generate an echo action for an target action.
chain(action[, source])
create an action chain from an action with an optional source action.
follow(source)
create an action chain from an source action.
listen(actionType, translator[, selector])
listen to a type of action to apply a translator to generate none, one or more forked actions.
Advanced
They should be used with a little bit carefulness.
thunk(action[, source]) => (dispatch)
explicitly create a thunk as the echo action for an optional source action.
squeak(action[, source])
explicitly create an common object echo action for an optional source action.
create(action[, source])
automatically create a thunk or an object by the existence of redux-thunk.
echos()
peek all current queued echo actions.
thunkEnabled()
query if the thunk mode is enabled.
enableThunk()
explicitly to enable thunk mode.
disableThunk()
explicitly to disable thunk mode.
translators([actionType])
peek all listening translators (as an object of action-type -> array-of-translator map) or an array of translators for the actionType.
unlisten(translator[, actionType])
remove a translator from all actions or a particular action.
Tour of Implementation
- Why not Observable?
- Design Principles
- Performance Concerns
The Last Of Last, actually
In this document, the word state is actually used with the meaning of sub-state since it is not referring the root state of the redux store.