React/Redux async api requests
So far, our application gets data from a hardcoded collection passed as a default state to the employees reducer function. However, for most of the web applications data should be loaded asyncronously from a remote server. The goal of this part is to provide this functionality with proper unit tests.
switch to the
03-asyn-api branch and run
For the purpose of moving the data out of our React/Redux application I've provided a simple API server based on Express framework (
api-server folder). Executing
npm start will spin up two node processes - one on port
3000 serving static assets of our application, another one on port
3001 providing JSON data from the API server. Pointing your browser to
http://localhost:3001/employees you should see the employees collection.
As you can see in the
api-server/routes/index.js, the reseponse is delayed by 1.5 second to simulate server/network latency, so we can see the preloading info.
Ok. So the first question should be: where do we trigger the http request? The answer being: as soon as our component that needs this data is loaded/mounted. React provides a life-cycle method that will serve the purpose:
If we simply adjusted the action creator function to return a http promise instead of a plain object we would see an error:
Actions must be plain objects. Use custom middleware for async actions. We will duly follow the advice and plug in the thunk library, that "can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met." (check the
src/index.js file for details).
If you want to know more about the motivation and internals of the library read this post on stack overflow
Now we are ready to make the API request and render the employee list. Let's take a look at the diagram:
EmployeeListcomponent is loaded, the
fetchEmployeesfunction, passed to the component via
mapDispatchToPropsfunction. This dispatches the
makeRequestaction is dispatched.
truechanging the loader state via the
fetchEmployeesaction creator. It returns a promise that when resolved dispatches the
returnEmployeesaction creator returns the loader property set to
falseas a payload.
To provide unit tests for our new async mechanism we have to add another two modules to our dev dependencies:
Nock's task is to intercept the http requests and set appropriate return value. Using it, we are in control of the result of a mocked request. To use the
dispatch method on the global store object we have to mock it first with
redux-mock-store - initially, we set the employees state to an empty collection and to check it for the http result after dispatching the action creator.
The last thing to do for our async requests is to provide a proper error handling for the API server response. We haven't done it yet for the sake of data flow clarity. To see the code changes checkout to the branch
03a-async-errors. To simulate an error, change the api url in the actions
index.js - you should have the error displayed instead of the employee list.
To provide error handling, the following changes have been made:
errorstate is not
EmployeeList component added
In addition to
thunk we'll make use of
redux-logger middleware that can help with debugging the application. Now, every dispatched action will be logged in the browser's console:
Thanks for reading the post and if it got you attention, I invite you to check the next part where I'll be writing about another important feature of single page applications - routing.