AJAX Requests in React: How and Where to Fetch Data

Dave Ceddia bio photo By Dave Ceddia Comment

One of the first questions new React developers have is, “How do I do AJAX requests in React?”

Here’s an answer to that question.

First: React itself doesn’t have any allegiance to any particular way of fetching data. In fact, as far as React is concerned, it doesn’t even know there’s a “server” in the picture at all.

React simply renders components, using data from only two places: props and state.

So therefore, to use some data from the server, you need to get that data into your components’ props or state.

You can complicate this process with services and data models (er, “build abstractions”) as much as you desire, but ultimately it’s just components rendering props and state.

Choose an HTTP Library

To fetch that data from the server, you’ll need an HTTP library. There are a ton of them out there. Ultimately they all do the same thing, but they have different features.

Like promises? Go with axios

Hate promises, but love callbacks? Take a look at superagent.

Rather use something soon-to-be-standardized? fetch might be your favorite.

The thing is, it doesn’t really matter. There’s no “best.”

Some will say that fetch is the best because it’s almost-a-standard, but I’m willing to bet that even after it’s actually a standard there will continue to be competing HTTP libraries that people will continue to use and prefer. So use what you like.

I like axios and that’s what I’ll show here. But seriously, if you don’t like it for some reason, go look at one of the other options.

Fetch That Data

Here’s a simple example component that fetches the posts from a subreddit (/r/reactjs in this case). Take a look at it, and we’ll go over how it works.

import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

class FetchDemo extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      posts: []
    };
  }

  componentDidMount() {
    axios.get(`http://www.reddit.com/r/${this.props.subreddit}.json`)
      .then(res => {
        const posts = res.data.data.children.map(obj => obj.data);
        this.setState({ posts });
      });
  }

  render() {
    return (
      <div>
        <h1>{`/r/${this.props.subreddit}`}</h1>
        <ul>
          {this.state.posts.map(post =>
            <li key={post.id}>{post.title}</li>
          )}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(
  <FetchDemo subreddit="reactjs"/>,
  document.getElementById('root')
);

How It Works

First, we import the axios library:

import axios from 'axios';

The constructor is pretty standard: call super, then initialize the state to have an empty array of posts.

componentDidMount is where the magic happens. This method will be executed when the component “mounts” (is added to the DOM) for the first time. This method is only executed once during the component’s life.

TL;DR: Fetch server data in the componentDidMount lifecycle method

It uses the axios.get function to fetch the data from the subreddit, based on the subreddit prop passed in during render at the bottom. The backticks are an ES6 template string, and it probably does what you think: the ${...} part is replaced by the value of that expression, so the URL passed to axios.get is actually http://www.reddit.com/r/reactjs.json.

Two things to note here, specific to Reddit:

  • You can tack on .json to the end of any subreddit URL and get a JSON representation of the posts there.

  • If you forget the www you’ll get a CORS error (at least, I did).

Since Axios uses promises, we chain the call with .then to handle the response. The posts are extracted after a little bit of transformation, and then the important bit:

The component’s state is updated by calling this.setState with the new array of posts. This triggers a re-render, and then the posts are visible.

That’s all there is to it!

Bonus: Loading Indicator

Can you think of how to modify the code to add a “Loading…” message while the request is in flight?

Hint: set a flag in state that will toggle once the request completes. Use that flag in the render function to show the loading indicator.

Download the example code here.

Unzip it, run npm install, then npm start.

You might also be interested in my book because it teaches React starting with the basics.

comments powered by Disqus