When you call an action creator, one the very first line of the action creator function, you make the ajax request. That's a network request that is going to reach out to that JSON API.
The key part to understand is that when we make that request, we go down to the next line of code where we form up that action object and return it. The time between those two steps, between making the request and returning the action is instantaneous.
As you very well know, whenever we make a network request to some outside API, it may take some amount of time to get a response back.
So, after we return our action from the action creator, at some point in the future, we get a response back from the JSON API.
So, between Ajax request issued and Action returned from action creator may be instantaneous, but the time between Action being returned from action creator and response from JSON API received may take longer.
Regardless how long it takes, by the time the action shows up inside of the reducer, it always has our data available from our API.
To give you a better idea, I have added a debugger
statement to one of my own reducers so we can look at the different values inside of there.
import { SAVE_COMMENT, FETCH_COMMENTS } from 'actions/types';
export default function(state = [], action) {
switch (action.type) {
case SAVE_COMMENT:
return [...state, action.payload];
case FETCH_COMMENTS:
debugger;
const comments = action.payload.data.map(comment => comment.name);
return [...state, ...comments];
default:
return state;
}
}
When I clicked the Fetch Comments button thats when it called the action creator and inside my sources tab I immediately hit the debugger
statement.
Here is evidence that whenever this action shows up inside a reducer, it has the response that it got from the API.
Now, lets remove the Redux Promise middleware and see what happens.
Middleware:
export default ({ children, initialState = {} }) => {
const store = createStore(
reducers,
initialState,
applyMiddleware(reduxPromise)
);
Middleware gone:
export default ({ children, initialState = {} }) => {
const store = createStore(reducers, initialState, applyMiddleware());
return <Provider store={store}>{children}</Provider>;
};
What's this?
The payload
is not a response coming back from the JSON API, instead its a pending Promise
, which means our request is still out on the network waiting to come back from the JSON API. So clearly, without Redux Promise middleware, our application will not work as expected.
Action creators were not developed to support asynchronous request, call it an oversight, I don't know.
We use middlewares like Redux Promise to look at actions that are about to be sent to a reducer and we have the opportunity to delay, log, modify or stop the action entirely and its only through these middlewares that we make these asynchronous requests work the way we expect it to. We are using Redux Promise because we want to inspect every action returned from an action creator and if it contains an API request or some asynchronous request, we want to delay it, so we can get that response to come back before the action goes on to the reducers. That is what Redux Promise does for us.