11.5 React Lifecycle

When first learning React, there are times when it can feel a little magical: make a change to a state variable, and viola, everywhere that displays that value will eventually update as well. The key word here is “eventually”. That is, it is important to recognize that things happen in React in a certain order. You can programmatically interact with this order by working with the React lifecycle methods.

Every component travels through a lifecycle of events. You have already encountered one of these events, the render() event. The render() event is triggered when the component is mounted (i.e., when it is created and inserted into the DOM) and when it is updated (i.e., when its props or state changes).

The act of mounting a component also generates events, and the most important of these is componentDidMount(), which is called after the first call to render(). This is typically where data would be fetched from an API. When an update occurs, React will call several events in a specific order; the most commonly used are shouldComponentUpdate(), render(), and then componentDidUpdate().

11.5.1 Fetching Data

In the last chapter, you learned how to use the fetch() function to retrieve data from an API. In React, we have to retrieve data at a specific point in the component’s life cycle. This is typically done during the componentDidMount event, which until React Hooks, required using a class component instead of a functional component. For instance, to fetch a list of paintings from an API, you would write the following:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { paintings: [] };
  }
  async componentDidMount() {
    try {
      const url =
         "http://randyconnolly.com/funwebdev/3rd/api/art/paintings.php";
      const response = await fetch(url);
      const jsonData = await response.json();
      this.setState( {photos: jsonData} );
    }
    catch (error) {
       console.error(error);
    }
  }
  ...
}

With Hooks, you can now also fetch data within functional components. Earlier, you learned about the useState() hook. There are in fact other Hooks methods. One of these is the useEffect() hook, which according to the official documentation lets you “perform side effects,” such as data fetching, subscribing to a service, or manually changing the DOM. These effects happen after the first render() call. Listing 11.9 demonstrates useEffect() is used within a component. Notice that useEffect() is passed to a function which is called by React after rendering.

Listing 11.9 Fetching data with useEffect().

import React, { useEffect, useState } from 'react';
import HeaderApp from './components/HeaderApp.js';
import PhotoBrowser from './components/PhotoBrowser.js';

function App() {
  const [photos, setPhotos] = useState([]);

  useEffect( () => {
    const url = "...";
    fetch(url)
      .then( resp => resp.json() )
      .then( data => setPhotos(data))
      .catch( err => console.error(err));
  });
  return (
    <main>
      <HeaderApp />
      <PhotoBrowser photos={photos} />
    </main>
  );
}