React and Redux – Async Status and Error Handling

cory

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 2 – Environment Setup

Part 3 – React Component Approaches

Part 4 – Initial App Structure

Part 5 – Intro to Redux

Part 6 – Actions, Stores and Reducers

Part 7 – Connecting React to Redux

Part 8 – Redux Flow

Part 9 – Async in Redux

Part 10 – Async Writes in Redux

Part 11 – Async Status and Error Handling

Part 12 – Testing React

Part 13 – Testing Redux

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

toast1

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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s