Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Integrate State Management with UX in React.js

Oct 21, 2020 • 6 Minute Read

Introduction

UX is very important when communicating to let the user know what's happening in your app. A common use case for this would be showing the user a loading interface before the actual interface is shown. This is usually done to allow some long-running background process to finish its work before updating state values of the main component. In this guide, we'll take a look at a simple approach to perform this effect.

Context

First, you have to simulate the long-running process in the form of fetching data from some third party API. For this, use this endpoint, which randomly spits out a quote from the hit TV series Breaking Bad (for more API endpoints in this context, please see https://github.com/shevabam/breaking-bad-quotes). The content of the response will be a JSON array with the following structure:

      
  {
    "quote": "I am not in danger
    

Setup

Create a React.js component that looks like the following:

      import React from 'react';
import $ from 'jquery';

export default class BBQuoteGenerator extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      quote: false
    }
  }

  render() {
    return (
      <div>
        <h1>
          Breaking Bad Quote of the Day
        </h1>
      </div>
    );
  }
}
    

The quotes state attribute will hold the current quote to be rendered in the app. Notice that even if you're expecting an array of values similar to the example shown in the previous section, its initial value is false. The logic behind this is that you would first check that the value is not false to display the actual content, indicating that data has indeed been loaded.

Creating the Loading UI

You can now extend the rendering part of the component by creating the following utility method that returns UI elements that display the quote if state.quote is not false. Otherwise, display some loading message to the user indicating that the app is still fetching data.

      renderQuote() {
  if(this.state.quote) {
    return (
      <div>
        <h2>
          <i>
            "{this.state.quote.quote}"
          </i>
        </h2>
        <h3>
          - {this.state.quote.author}
        </h3>
      </div>
    );
  } else {
    return (
      <div>
        Loading...
      </div>
    );
  }
}
    

The function simply returns a single jsx element containing the interface. The else portion indicates a false value for quote and thus renders some loading message. You can easily substitute this with your own loading splash message as long as the return statement returns a single element. For now, it's just simple text that is being returned to indicate loading.

You can then invoke the function within the main render call:

      render() {
  return (
    <div>
      <h1>
        Breaking Bad Quote of the Day
      </h1>
      {this.renderQuote()}
    </div>
  );
}
    

Fetching Data

In order to have quote be not false, that is, populate it with actual data, you'd have to create a function that does two things:

  1. Fetches the data from an API
  2. Updates the state.quote value of the component to force a re-render of the UI

Create a function called fetch() that does the following:

      fetch() {
  var context = this;

  $.ajax({
    url: "https://github.com/shevabam/breaking-bad-quotes",
    dataType: "json",
    method: "GET",
    success: function(response) {
      var q = response[0];

      context.setState({
        quote: q
      });
    }
  });
}
    

The context variable is needed to create a reference to this and represent the instance of the component. This will allow the call of setState to be invoked within the success callback of the AJAX call. Since the expected response is an array, you have to get the first element (0) instead of storing the entire response in quote. Setting the data to quote will now make the data not false and render the actual UI it was intended to display.

Calling Fetch When Component is Loaded

Now you have make sure that fetch is triggered as soon as the component is loaded for the first time. To do this, override the componentDidMount function of the component and call fetch within it.

      componentDidMount() {
  this.fetch();
}
    

Overall Code

The final code looks like the following:

      import React from 'react';
import $ from 'jquery';

export default class BBQuoteGenerator extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      quote: false
    }
  }

  componentDidMount() {
    this.fetch();
  }

  fetch() {
    var context = this;

    $.ajax({
      url: "https://github.com/shevabam/breaking-bad-quotes",
      dataType: "json",
      method: "GET",
      success: function(response) {
        var q = response[0];

        context.setState({
          quote: q
        });
      }
    });
  }

  renderQuote() {
    if(this.state.quote) {
      return (
        <div>
          <h2>
            <i>
              "{this.state.quote.quote}"
            </i>
          </h2>
          <h3>
            - {this.state.quote.author}
          </h3>
        </div>
      );
    } else {
      return (
        <div>
          Loading...
        </div>
      );
    }
  }

  render() {
    return (
      <div>
        <h1>
          Breaking Bad Quote of the Day
        </h1>
        {this.renderQuote()}
      </div>
    );
  }
}
    

Conclusion

Displaying loading messages initially to the user is a good UX approach to indicate that something is still happening behind the scenes. Using React.js's state management mechanism, you can use the value of your data to determine when loading is displayed or when the actual UI should be displayed. This can be wrapped in a utility function within the component and called in the main render function. As seen in this example, the main render UI did not have to have any logic in it since the UI switches from loading to display depending on the state value quote as implemented in the logic of renderQuote.

For any questions/concerns, or if you simply want to chat about programming in general, hit me up @happyalampay!