Using React: Part 5: Playing with AJAX

Learning React

Using React

React is a popular JavaScript library for creating user interfaces. It combines many features of JavaScript ES6 together to create a powerful way to quickly create front-end functionality.

Playing with AJAX

In the previous part, Handling Events, a complex example was created based on the user interacting with a button that used a function as part of another scope to both handle an event and interact with a “lifted” state in a “parent” component.

While user interactions can drive interactions within an interface, often it is useful to base those actions on external data that the user then manipulates in different ways. To gather that data, additional functionality is needed: AJAX.

While originally meaning for “Asynchronous JavaScript And XML,” AJAX has become a catch-all term for getting data from a source after a page has initially loaded and then performing actions on it or allowing the user’s interactions to request more data or actions. Put in its most basic terms: “Get data, do something.”

AJAX in React

In other web development settings, something like jQuery’s AJAX or Axios might be used as the framework and function calls to handle AJAX requests and their results. However, React does not always play well with other frameworks that do or have the potential to change the DOM. Because React also changes it, using different frameworks that do the same thing can create possible collisions.

That doesn’t mean that with careful use, for example, jQuery’s AJAX could not be used in ways that avoided these problems, but there is an easier solution: window.fetch. in lieu of using something else (although Axios could work), the build-in functionality of modern web browsers can be used without adding more libraries or modules.

When to fetch()

While it may seem to make sense to have a fetch() call as part of, say, render(), this is a bad idea. The render() function of a component has the potential to be called multiple times or not at all depending on other factors and if the setState() function is also being used. Placing the fetch() in the constructor, in a similar way, is also problematic: the component might be created but not yet rendered.

Components Mount

The lifecycle of React components is three phases: mounting, updating, and unmounting. These can be thought of as “being created,” “rendering,” and “being destroyed.”

In previous examples, the code was broken up into doing things as part of the constructor or as part of the rendering function. Internally, React does not think in these terms. Instead, it uses three verbs: will, did, and should. These verbs pair with the lifecycle.

Mounting Phase:

Updating Phase

Unmounting Phase

Moving through the phases based on the previous code, the constructor is called once, the render() function is called next. Once it passes to the updating phase, render() is called again.

Four new functions were introduced in the above breakdown: componentDidMount(), shouldComponentUpdate(), componentDidUpdate(), and componentWillUnmount().

Thinking back on where to put the initial fetch() call, then, thinking about componentDidMount() seems worth pursuing. And, in fact, that is what the documentation recommends:

If you need to load data from a remote endpoint, this is a good place to instantiate the network request.

Updating ShoppingList

Using the componentDidMount() function as a place for fetch() allows for placing the code in a part of the mounting phase after the object has both been constructed and rendered once. This also allows for using setState() to cause an additional render() to happen if new data is passed into the function.


import React from 'react';
import Item from './Item.js';
import AddButton from './AddButton.js';

class ShoppingList extends React.Component {

  constructor(props) {

    this.state = {
      items: []

    // Since addItem will be called within another scope,
    //  we bind() it to the 'this' inside ShoppingList.
    this.addItem = this.addItem.bind(this);


  addItem() {

    const items = this.state.items.concat("New Item");

    this.setState({items: items});


  componentDidMount() {
      .then(response => response.json())
        (data) => {
            this.setState({ items: data })
          (error) => {
            //Handle errors

  render() {
    return (
        <div><AddButton onClick={this.addItem} /></div>
        {, index) => (
              <Item name={item} key={index} />

export default ShoppingList;

The use of fetch() is following a promise structure. It requests data, then transforms that text into data via json(). Then, it acts on one of two arrow functions. If everything succeeded, the data is passed to setState(). If not, the last arrow function handles errors in some way.


This example used a simple PHP script that returned JSON content so that the React example could parse and use it.



header("Access-Control-Allow-Origin: *");
header('Content-Type: application/json');

echo json_encode(array(
    "Cream Cheese"


One of the important aspects when using fetch() with other services and sites is being aware of Cross-Origin Resource Sharing (CORS). In order to protect users, modern web browsers implement security settings that check the domain and the headers of content it receives.

In order for this example server to work, it needed to send the header Access-Control-Allow-Origin to signal that, yes, other sites could access this data safety. It also needed to use the content-type “application/json” to let other clients know the content was, in fact, JSON.