According to the docs, \"Without middleware, Redux store only supports synchronous data flow\". I don\'t understand why this is the case. Why can\'t the container component
To answer the question that is asked in the beginning:
Why can't the container component call the async API, and then dispatch the actions?
Keep in mind that those docs are for Redux, not Redux plus React. Redux stores hooked up to React components can do exactly what you say, but a Plain Jane Redux store with no middleware doesn't accept arguments to dispatch
except plain ol' objects.
Without middleware you could of course still do
const store = createStore(reducer);
MyAPI.doThing().then(resp => store.dispatch(...));
But it's a similar case where the asynchrony is wrapped around Redux rather than handled by Redux. So, middleware allows for asynchrony by modifying what can be passed directly to dispatch
.
That said, the spirit of your suggestion is, I think, valid. There are certainly other ways you could handle asynchrony in a Redux + React application.
One benefit of using middleware is that you can continue to use action creators as normal without worrying about exactly how they're hooked up. For example, using redux-thunk
, the code you wrote would look a lot like
function updateThing() {
return dispatch => {
dispatch({
type: ActionTypes.STARTED_UPDATING
});
AsyncApi.getFieldValue()
.then(result => dispatch({
type: ActionTypes.UPDATED,
payload: result
}));
}
}
const ConnectedApp = connect(
(state) => { ...state },
{ update: updateThing }
)(App);
which doesn't look all that different from the original — it's just shuffled a bit — and connect
doesn't know that updateThing
is (or needs to be) asynchronous.
If you also wanted to support promises, observables, sagas, or crazy custom and highly declarative action creators, then Redux can do it just by changing what you pass to dispatch
(aka, what you return from action creators). No mucking with the React components (or connect
calls) necessary.