Another version of redux-effects handling error action properly.
npm install --save redux-effects-steps
import { createStore, applyMiddleware } from 'redux';
import stepsMiddleware from 'redux-effects-steps';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(
stepsMiddleware
)
);
import { createAction } from 'redux-actions';
import { steps } from 'redux-effects-steps';
import { fetchrRead } from 'redux-effects-fetchr';
const fetchUserRequest = createAction('FETCH_USER_REQUEST');
const fetchUserSuccess = createAction('FETCH_USER_SUCCESS');
const fetchUserFail = createAction('FETCH_USER_FAIL');
function fetchUser({ user }) {
return steps(
fetchUserRequest(),
fetchrRead('users', { user }),
[fetchUserSuccess, fetchUserFail]
);
}
const promise = store.dispatch(fetchUser({ user }));
Example:
const promise = store.dispatch(steps(
originAction,
[firstSuccess, firstFailure],
[secondSuccess, secondFailure]
));
is evaluated by redux-effects-steps like this:
const promise = store.dispatch(originAction)
.then((result) => store.dispatch(firstSuccess(result)), (error) => store.dispatch(firstFailure(error)))
.then((result) => store.dispatch(secondSuccess(result)), (error) => store.dispatch(secondFailure(error)));
Async action returns a Promise object when it's dispatched. If the dispatched action fails, the returned Promise will be rejected.
Sync action returns an object which is not a Promise (by default, dispatched action itself.) when it's dispatched. If the action represents fail, it should be error action.
redux-effects:
import { createAction } from 'redux-actions';
import { bind } from 'redux-effects';
import { fetch } from 'redux-effects-fetch';
const success = createAction('FIND_USER_SUCCESS');
const failure = createAction('FIND_USER_FAILURE');
function findUser(condition) {
return bind(fetch('/api/users', {method: 'POST', body: condition}), success, failure);
}
const finalPromise = store.dispatch(findUser(condition));
If fetch()
action fails, the
error action
created by failure()
is dispatched.
And then, redux-effects resolves the next Promise, so the finalPromise
isn't rejected.
This is the problem when the action creator is used with redux-form.
In this example, onSubmit()
handler always succeed if the action fails.
reduxForm({ form: 'myForm', fields: [...] }, null, {
onSubmit:(values, dispatch) => dispatch(findUser(values.user))
})(MyForm)
On the other hand, redux-effects-steps rejects the next Promise when error action is dispatched.
redux-effects provides an action creator takes just one step.
import { bind } from 'redux-effects';
const action = bind(fetch(), success, failure);
redux-effects-steps provides an action creator takes multiple steps.
import { steps } from 'redux-effects-steps';
const action = steps(begin(),
[fetch('/api/users')],
[success, failure]
);
origin
(Array|Object)- One of the:
action
(Object): A FSA compliant action object.actions
(Array): An array of actions.
- One of the:
steps
(Array)- Each element is in a
[success, failure]
tuple Array. success
andfailure
are one of the:- If
failure
is not needed, you can pass justsuccess
instead of an Array.
- Each element is in a
(Object): A FSA compliant action object.