Is there a way to dispatch actions from within an action ?
esperancaJS opened this issue · comments
In more complex Actions it would make the code simpler to separate it into other actions.
Wondering if there is a simple way to do this already.
Thanks!
Currently I've found this solution:
const mapActions = ({setState}) => ({
startComplexFlow(state) {
setState({ startComplexFlowLoading: true });
// dispatching an action within an action
mapActions({setState}).continueComplexFlow(state);
still curious to see how it'll work with Kiho/redux-zero@d63baca
Does the following looks like a good idea ? Or can you foresee some obvious pitfalls ?
Plot twist : there is no need to change anything in redux-zero to make it work.
It's nothing more than a wrapper around actions - just like bindActions.
./ConnectedComponent.js
import {connect} from 'redux-zero/preact'
import chainedActions from './chainedActions'
import actions from './actions'
....
export default connect(mapState, chainActions(actions))(Component)
Basically, an object containing all actions is passed down as a third argument to each individual action.
So we can now 'chain' our actions like below :
./actions.js
export default (store, ownProps) => ({
test0: (state, args, actions) => {
actions.test1(0)
return {test: 0} // should return before test1
},
test1: async (state, args, actions) => {
console.log(args) // should log 0
await actions.test2()
return {test: 1} // should return after test2
},
test2: (state, args, actions) => {
actions.test3(2, 1000) // should 1s after test2
return {test: 2}
},
test3: async (state, args, actions) => {
console.log(args) // should log 2
await actions.test4(null, 1000) // should wait for 1s
return {test: 3} // should return immediately after test4
},
test4: (state, args, actions) => ({test: 4})
})
./chainActions.js
EDIT: mapState & mapAction help me to 'namespace' my store - but that's beyong the scope of this issue
export default userActions =>
(store, ownProps, mapState = state => state, mapAction = res => res) => {
const actions = {}
userActions = userActions(store, ownProps)
const chainActions = () => {
const actions = {}
for(let k in userActions) {
actions[k] = (arg, ms = 0) =>
new Promise(res =>
setTimeout(async () => {
store.setState(
mapAction(
await userActions[k](
mapState(store.getState()),
arg,
chainActions()
) || {}
)
)
res()
}, ms))
}
return actions
}
for(let k in chainActions()) {
actions[k] = async (state, arg) => mapAction(
await userActions[k](mapState(state), arg, chainActions()) || {}
)
}
return actions
}
Sorry for the long post & the funny indentation.
I think they're both good approaches to the problem, I just don't see why you should do this in the first place.
If your actions is too big, it should probably be splitted anyway.