Description
Hello, we are trying to create modules made of a redux reducer and/or a middleware. The modules are to be reused and distributed, mostly like Ducks does, but also supporting middlewares.
We are using redux actions and trying to do something useful asynchronously, like reading a file or something from the database, and also allow a chain of dependency where modules' middlewares/reducers can rely on the state/payload of the module it depends on, and use it to build and return a new state.
Something like:
module 1
-> dispatch action to read something async
-> query database middleware await data from database
-> run all other modules (async/sync) middlewares
-> reducer consumes data and build a new state
-> then it's passed to module 2 reducer and so on...
For doing so we are trying to run through a chain of (synchronous and asynchronous) side-effects in middlewares.
We don't want to do anything other than returning the FSA object when defining actions, so we don't restrict the data gathering logic and any other business logic only to the module that creates the action and centralize them in middlewares.
import {createStore, applyMiddleware} from 'redux'
import {createAction, handleActions} from 'redux-actions'
import promiseMiddleware from 'redux-promise'
const BOOT = 'BOOT'
const AFTER_BOOT = 'AFTER_BOOT'
const AFTER_AFTER_BOOT = 'AFTER_AFTER_BOOT'
const someApi = {
get(id) {
return Promise.resolve({
name: 'yeah'
})
}
}
const bootAction = createAction(BOOT)
const afterBootAction = createAction(AFTER_BOOT, async (id) => {
const result = await someApi.get(id)
return result
})
const afterAfterBootAction = createAction(AFTER_AFTER_BOOT, async (id) => {
const result = await someApi.get(id)
return result
})
const initialState = {foo: 'bar'}
const reducer = (state = initialState, action) => {
switch (action.type) {
case AFTER_BOOT:
return {
...state,
foo: 'baz'
}
case AFTER_AFTER_BOOT:
return {
...state,
foo: 'rock'
}
default:
return state
break
}
}
const middlewares = [
function middle({getState, dispatch}) {
// Note the async keyword.
return next => async (action) => {
if (action.type == BOOT) {
const sideffectA = await dispatch(afterBootAction(2))
}
if (action.type == AFTER_BOOT) {
const sideffectB = await dispatch(afterAterBootAction(3))
}
return next(action)
}
},
promiseMiddleware
]
const store = createStore(reducer, initialState, applyMiddleware(...middlewares))
// First action, and should fire other side-effects.
store.dispatch(bootAction())
console.log(store.getState(), "It should print {foo: 'rock'}")
We are doing this as part of our Choko Redux project.