# Getting Real with an API

By [safeboys](https://paragraph.com/@safeboys) · 2023-04-04

---

> _Do you know the Hacker News platform? It’s a great news aggregator about tech topics. In this book, you will use the Hacker News API to fetch trending stories from the platform. There is a basic and search API to get data from the platform. The latter one makes sense in your case to search stories on Hacker News._

Lifecycle Methods
-----------------

You will need the knowledge about React lifecycle methods before you can start to fetch data. These methods are a hook into the lifecycle of a React component. They can be used in ES6 class components, but not in functional stateless components. Do you remember when a previous chapter taught you about JavaScript ES6 classes and how they are used in React? Apart from the render() method, I mentioned several methods that can be overwritten in a React ES6 class component. All of these are the lifecycle methods. Let’s dive into them: You already know two lifecycle methods in a ES6 class component: constructor() and render(). The constructor is only called when an instance of the component is created and inserted in the DOM. The component gets instantiated. That process is called mounting of the component. The render() method is called during the mount process too, but also when the component updates. Each time when the state or the props of a component change, the render() method is called. Now you know more about the two lifecycle methods and when they are called. You already used them as well. But there are more of them. The mounting of a component has two more lifecycle methods: componentWillMount() and componentDidMount(). The constructor is called first, componentWillMount() gets called before the render() method and componentDidMount() is called after the render() method. Overall the mounting process has 4 lifecycle methods. They are invoked in the following order:

*   constructor()
    
*   componentWillMount()
    
*   render()
    
*   componentDidMount()
    

But what about the update lifecycle of a component that happens when the state or the props change? Overall it has 5 lifecycle methods in the following order:

*   componentWillReceiveProps()
    
*   shouldComponentUpdate()
    
*   componentWillUpdate()
    
*   render()
    
*   componentDidUpdate()
    

Last but not least there is the unmounting lifecycle. It has only one lifecycle method: componentWillUnmount().

After all, you don’t need to know all of these lifecycle methods from the beginning. It can be intimidating yet you will not use all of them - even in a mature React application. Still, it is good to know that each lifecycle method can be used for specific use cases:

*   constructor(props) - It is called when the component gets initialized. You can set an initial component state and bind useful class methods during that lifecycle method.
    
*   componentWillMount() - It is called before the render() lifecycle method. That’s why it could be used to set internal component state, because it will not trigger a second rendering of the component. Generally it is recommend to use the constructor() to set the initial state.
    
*   render() - The lifecycle method is mandatory and returns the elements as an output of the component. The method should be pure and therefore shouldn’t modify the component state. It gets an input as props and state and returns an element.
    
*   componentDidMount() - It is called only once when the component mounted. That’s the perfect time to do an asynchronous request to fetch data from an API. The fetched data would get stored in the internal component state to display it in the render() lifecycle method.
    
*   componentWillReceiveProps(nextProps) - The lifecycle method is called during an update lifecycle. As input you get the next props. You can diff the next props with the previous props (this.props) to apply a different behavior based on the diff. Additionally you can set state based on the next props.
    
*   shouldComponentUpdate(nextProps, nextState) - It is always called when the component updates due to state or props changes. You will use it in mature React applications for performance optimizations. Depending on a boolean that you return from this lifecycle method, the component and all its children will render or will not render on an update lifecycle. You can prevent the render lifecycle method of a component.
    
*   componentWillUpdate(nextProps, nextState) - The lifecycle method is immediately invoked before the render() method. You already have the next props and next state at your disposal. You can use the method as last opportunity to perform preparations before the render method gets executed. Note that you cannot trigger setState() anymore. If you want to compute state based on the next props, you have to use componentWillReceiveProps().
    
*   componentDidUpdate(prevProps, prevState)- The lifecycle method is immediately invoked after the render() method. You can use it as opportunity to perform DOM operations or to perform further asynchronous requests.
    
*   componentWillUnmount() - It is called before you destroy your component. You can use the lifecycle method to perform any clean up tasks
    

The constructor() and render() lifecycle methods are already used by you. These are the commonly used lifecycle methods for ES6 class components. Actually the render() method is required, otherwise you wouldn’t return a component instance.

Fetching Data Now you are prepared to fetch data from the Hacker News API. I mentioned one lifecycle method that can be used to fetch data: componentDidMount(). You will use the native fetch API to perform the request. Before we can use it, let’s set up the url constants and default parameters to breakup the API request into chunks

**src/App.js**

    import React, { Component } from 'react';
    import './App.css';
    const DEFAULT_QUERY = 'redux';
    const PATH_BASE = 'https://hn.algolia.com/api/v1';
    const PATH_SEARCH = '/search';
    const PARAM_SEARCH = 'query=';
    ...
    

In ES6 JavaScript you can use template strings to concatenate strings. You will use it to concatenate your url for the API endpoint

**Code Playground**

    // ES6
    const url = `${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${DEFAULT_QUERY}`;
    // ES5
    var url = PATH_BASE + PATH_SEARCH + '?' + PARAM_SEARCH + DEFAULT_QUERY;
    console.log(url);
    // output: https://hn.algolia.com/api/v1/search?query=redux
    

That will keep your url composition flexible in the future. But let’s get to the API request where you will use the url. The whole data fetch process will be presented at once, but each step will get explained afterward.

**src/App.js**

    ...
    class App extends Component {
    constructor(props) {
    super(props);
    this.state = {
    result: null,
    searchTerm: DEFAULT_QUERY,
    };
    this.setSearchTopstories = this.setSearchTopstories.bind(this);
    this.fetchSearchTopstories = this.fetchSearchTopstories.bind(this);
    this.onSearchChange = this.onSearchChange.bind(this);
    this.onDismiss = this.onDismiss.bind(this);
    }
    setSearchTopstories(result) {
    this.setState({ result });
    }
    fetchSearchTopstories(searchTerm) {
    fetch(`${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${searchTerm}`)
    .then(response => response.json())
    .then(result => this.setSearchTopstories(result));
    }
    componentDidMount() {
    const { searchTerm } = this.state;
    this.fetchSearchTopstories(searchTerm);
    }
    ...
    }
    

A lot of things happen in the code. I thought about it to break it into smaller pieces. Then again it would be difficult to grasp the relations of each piece to each other. Let me explain each step in detail.

First, you can remove the artificial list of items, because you return a result from the Hacker News API. The initial state of your component has an empty result and default search term. The same default search term is used in the search field and in your first request. Second, you use the componentDidMount() lifecycle method to fetch the data after the component did mount. In the very first fetch the default search term from the component state is used. It will fetch “redux” related stories, because that is the default parameter. Third, the native fetch is used. The JavaScript ES6 template strings allow it to compose the url with the searchTerm. The url is the argument for the native fetch API function. The response needs to get transformed to json, that’s a mandatory step in a native fetch, and can finally be set in the internal component state. Last but not least, don’t forget to bind your new component methods. Now you can use the fetched data instead of the artificial list of items. However, you have to be careful again. The result is not only a list of data. It’s a complex object with meta information and a list of hits (stories).⁷² You can output the internal state with console.log(this.state); in your render() method to visualize it. Let’s use the result to render it. But we will prevent to render anything - return null - when there is no result. Once the request to the API succeeded, the result is saved to the state and the App component will re-render with the updated state.

**src/App.js**

    class App extends Component {
    ...
    render() {
    const { searchTerm, result } = this.state;
    if (!result) { return null; }
    return (
    <div className="page">
    ...
    <Table
    list={result.hits}
    pattern={searchTerm}
    onDismiss={this.onDismiss}
    />
    </div>
    ); }}
    

Let’s recap what happens during the component lifecycle. Your component gets initialized by the constructor. After that it renders for the first time. But you prevent to display it, because the result is empty. Then the componentDidMount() lifecycle method runs. In that method you fetch the data from the Hacker News API asynchronously. Once the data arrives, it changes your internal component state. After that the update lifecycle comes into play. The component runs the render() method again, but this time with populated data in your internal component state. The component and thus the Table component with its content gets re-rendered. You used the native fetch API that is supported by most browsers to perform an asynchronous request to an API. The create-react-app configuration makes sure that it is supported in every browser. There are third party node packages that you can use to substitute the native fetch API: superagent⁷³ and axios⁷⁴. Back to your application: The list of hits should be visible now. But the “Dismiss” button is broken.

---

*Originally published on [safeboys](https://paragraph.com/@safeboys/getting-real-with-an-api)*
