Welcome to Part 11 of this comprehensive review and summary of Cory House’s Pluralsight course Building Applications with React and Redux in ES6.
Cory is a Microsoft MVP in C#, founder of OutlierDeveloper.com, avid tech reader, and speaker.
He believes in clean code, pragmatic development, and responsive native UIs.
Also in this series:
Part 1 – Introduction and Background
Part 3 – React Component Approaches
Part 4 – Initial App Structure
Part 6 – Actions, Stores and Reducers
Part 7 – Connecting React to Redux
Part 10 – Async Writes in Redux
Part 11 – Async Status and Error Handling
Async Status and Error Handling
Intro
Cory runs through the issues we need to address in this module:
- No initial loading indicator
- No feedback upon clicking save
- API fails silently
Create Preloader Component
We start by creating LoadingDots.js
This is a component which displays a list of dots. We can configure the rate of display and the number of dots as we like.
Cory demonstrates this by adding it beside the page links. Next we want to display this only when an AJAX call is being made.
Create AJAX Status Actions
We add ajaxStatusActions.js and in here we have a function beginAjaxCall.
Create AJAX Status Reducer
We add ajaxStatusReducer.js with two functions: ajaxStatusReducer and a helper function called actionTypeEndsInSuccess.
ajaxStatusReducer works by incrementing a counter called state.
actionTypeEndsInSuccess checks to see if the last 8 characters of the action type are ‘_SUCCESS’
This means we have a generic solution that will work for all of our AJAX calls.
We must also remember to add our new reducer to our root reducer.
Call Begin AJAX in Thunks
First we update courseActions and authorActions, adding:
import {beginAjaxCall} from ‘./ajaxStateActions’.
Then we update loadCourses and loadAuthors, adding more calls to dispatch, with beginAjaxCall() as our parameter.
Cory discusses optimistic updates in Ajax here as well.
Hide Preloader Based on Status
We add a mapsStateToProps function in App.js, and this sets our loading property based on whether or note we have any AJAX calls in progress. We also need to this class to use connect.
Next we update Header.js to use our new boolean loading property.
We we run up our app, we see the following error in the console:
Uncaught Error: Reducer “ajaxCallsInProgress” returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined.
This turns out to be just a simple typo in initialState.js
Once fixed, we see the preloader runs until our data is loaded.
Use Promises to Wait for Thunks
Cory shows us that when we click Save on the manage courses page, it immediately takes us to the course list page. This is a problem because it shows stale data for a split second before the list updates.
We can improve the user experience by only moving to the new screen when the update is complete. We achieve this using promises.
In the saveCourses function, we simply add a .then(() => this.redirect()) function, and create a redirect function using existing code.
We see a small improvement in the user experience, but what we really need is a way to provide immediate feedback to the user that the save button was clicked.
Create Form Submission Loading Indicator
We disable the submit button on click, and show the loading dots component.
This involves setting a saving property to true in our saveCourse function and then back to false again in our new redirect function.
We pass our saving property down to CourseForm and make some renames from loading to saving. This gets our app running as intended.
Display Save Notification
In this clip we display a save success notifications, using John Papa’s Toastr library.
This library includes CSS, and we need to import this into index.js
We see that toastr is really easy to use – we just call toastr.success with our success message and voila!
That was the happy path 🙂
Next we look at the sad path 😦
Error Handling
As we are using a mock Api, it is now much easier to test a failing AJAX call.
We see that the application is stuck – the preloader runs forever and we go nowhere.
To improve this experience, we look at our saveCourse function in ManageCoursePage.js – we’re missing any error handling here!
We take advantage of our new toastr library to notify our users
.catch(error => {
toastr.error(error);
});
We also reset our saving property back to false so that the user can try again.
When we run this up, we can see that the toast pops up correctly and the save button is re-enabled, but the preloader continues to run on and on. To fix this we need to dispatch a new action.
Cory shows us how to add a new action type, AJAX_CALL_ERROR, add the corresponding action creator in actionStatusActions.js, and update our course thunk to dispatch our ajaxCallError function.
We see this has fixed it: as soon as the toast pops up, the loading dots disappear!
Continue to Part 12 – Testing React