HTTP-API Integration with React Lifecycle-Methods and Hooks
Tags: react, javascript
Published: 2019-02-14 15:31:23

---
title: HTTP-API Integration with React Lifecycle-Methods and Hooks
published: true
canonical_url: https://www.moesif.com/blog/technical/HTTP-API-Integration-with-React-Lifecycle-Methods-and-Hooks/
tags: react, javascript
---

## Why

When we create a Single Page Application (SPA), we often need to integrate APIs. Sometimes third-party APIs, but at least our own back-ends to get the data we need to display. These APIs are based on the HTTP or WebSocket protocol, each having its requirements for connection setup and tear down.

In this article, I explain the basic integration of HTTP APIs.

## What

[HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) is a stateless protocol. It's the simplest way to get data from the server.

- call the [fetch function](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
- get a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- wait until the promise resolves
- update the application with the new data

Sometimes HTTP requests fail, and sometimes we cancel them because the data hasn't arrived yet but isn't needed anymore.

### Lifecycle Methods

[Lifecycle methods](https://reactjs.org/docs/state-and-lifecycle.html) are component methods with special names that are called by React to specific events.

For example, `componentDidMount` will be called after React rendered a component into the DOM.

### Hooks

[Hooks](https://reactjs.org/docs/hooks-intro.html) are a new part of React and allow us to do things we did with lifecycle methods, but without the need to create a component class, they work with function components only.

For example, the callback supplied to the `useEffect` hook function will be called every time React rendered a component.

## How

First, let us integrate via lifecycle methods.

## Lifecycle Methods

To use lifecycle methods, we need to create a class component that has three methods, `render`, `componentDidMount` and `componentWillUnmount`.

```javascript
class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      loading: true,
      data: null,
      error: null
    };
  }

  async componentDidMount() {
    this.abortController = new AbortController();

    try {
      const response = await fetch(API_URL, {
        signal: this.abortController.signal
      });

      if (response.status >= 300)
        throw new Error(response.statusText);

      const data = await response.json();

      this.setState({ loading: false, data });
    } catch (e) {
      if (e.name != "AbortError") this.setState({ error: e.message });
    }
  }

  componentWillUnmount() {
    this.abortController.abort();
  }

  render() {
    const { data, error, loading } = this.state;

    if (!!error) return <h2>{error}</h2>;

    if (loading) return <h2>Loading...</h2>;

    return <h2>{data}</h2>;
  }
}
```

Let's go through this step-by-step.

**1 - Define the state in the `constructor`**

For an HTTP request, we need three states. `loading`, `data` and `error`.

**2 - Start the request in the `componentDidMount` lifecycle method**

We use an asynchronous function here, so we can handle the promises of the `fetch` function with `await`.

First, we need to define an [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController#Examples) that allows us to cancel the HTTP request. Then we call `fetch` in a `try` block and `await` its `response`.

We also pass the `signal` of the `abortController` into the fetch call to wire up the controller with the request. This signal is used to cancel the request when we call the `abort` method of the `abortController`.

If the `status` of our request isn't an error code, we assume the data is ready to be parsed; we add it to our state and set `loading` to `false`.

If the `fetch` call throws an error, we get an error code from the server, or the `abort` method of the `abortController` is called, we `catch` the error and render an error.

**3 - Cancel the request in `componentWillUnmout` the lifecycle method**

Since we saved a reference to the `abortController` to `this`, we can use it in the `componentWillUnmount` method. This method is called by React right before the component gets removed from the DOM.

The call to `abort` leads to a rejection of the `fetch` promise.

In the `catch` block we only call the `setState` method if the error isn't an `AbortError` because we know that React will remove our component from the DOM.

**4 - Render the different states**

Finally, we have to render the different states. The main logic is inside the lifecycle methods, so the `render` method doesn't need much logic anymore.

### Hooks

To use hooks, we have to create a functional component. In the function we have to use two hooks, `useState` to store our state and `useEffect` to handle the API call.

```javascript
function MyComponent() {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [data, setData] = useState(null);

  useEffect(async () => {
    const abortController = new AbortController();

    try {
      const response = await fetch(API_URL, {
        signal: abortController.signal
      });

      if (response.status >= 300)
        throw new Error(response.statusText);

      const data = await response.json();

      setData(data);
      setLoading(false);
    } catch (e) {
      if (e.name != "AbortError") setError(e.message);
    }

    return () => abortController.abort();
  }, []);

  if (!!error) return <h2>{error}</h2>;

  if (loading) return <h2>Loading...</h2>;

  return <h2>{data}</h2>;
}
```

**1 - First setup the state with the `useState` hook**

The `useState` hook takes an initial value and returns a new state-variable and a setter function. Every time the setter is called, it will cause React to re-render the component with the new value inside the state-variable.

**2 - Start the request with the `useEffect` hook**

The `useEffect` hook takes a callback that is called every time React renders the component (i.e. when we call a setter function).

When we pass an empty array as the second argument to `useEffect` the callback is only executed after the first render. This allows us to emulate the behavior of the `componentDidMount` lifecycle method.

The logic in the callback is mostly the same as in the lifecycle method example. The main differences are the missing `this`, because we don't have a class component and that we use the setters of the `useState` hooks.

**3 - Cancel the request with the returned function**

The function we return from the callback supplied to the `useEffect` hook is executed before the component is removed from the DOM. This allows us to emulate the behavior of the `componentWillUnmout` lifecycle method.

We call the `abort` method of the `abortController` and are done.

**4 - Render the different states**

To render we can use the state-variables returned by the `useState` hooks. Most of the logic is inside the callback we passed to `useEffect` so not much to do here.

## API Analytics & Monitoring

Btw, if you curious about how to add [API analytics](https://www.moesif.com/features/api-analytics) to your React SPA, check out [this example](https://github.com/Moesif/moesif-react-boilerplate-example).

## Conclusion

The two ways to integrate API calls into React components are mostly a matter of taste. Some people prefer an object-oriented approach; others want to be more functional. React lets you go either way, both allow for error handling and cancelation.

---

**Moesif is the most advanced API Analytics platform, supporting REST, GraphQL and more. Thousands of API developers process billions of API calls through Moesif for debugging, monitoring and discovering insights.**


## <a href="https://www.moesif.com/features?int_source=blog">Learn More</a>

---

*Originally published at [www.moesif.com](https://www.moesif.com/blog/technical/HTTP-API-Integration-with-React-Lifecycle-Methods-and-Hooks/).*