How to make AJAX requests in React?

If I were to pick one topic that is mentioned a lot in forums about React or frontend in general it would be making an AJAX request in React powered applications.

The biggest confusion is rooted in the fact that React is often advertised as a framework, and people familiar with frameworks such as AngularJS are used to making API calls with things like $http and similar helper libraries provided by Angular itself. This is not the case in React as React is “just” a view library with some state management and lifecycle methods*.

So — how do you make an AJAX request when there is not library provided for you?

You are free to use any 3rd party library! You can use the native browser implementation of fetch (you might want to also include whatwg-fetch polyfill for those stuck with outdated browsers) or use axios. I personally prefer the latter one as axios has a simple API and works in majority of the browsers.

To be able to use axios all you need to know is how promisses work — if you ever used jQuery.ajax before, you should be ready to go.

Lets explain the usage based on a simple GET request:

axios.get('http://example.com/posts/1')
.then(function (response) {
console.log(response);
})

We are sending a GET request to specified URI and loging the response. Axios already assumes that the response will be a JSON object for us, so we don’t need to specify any additional options.

As you can see, making an AJAX request in React is not much different than making it with jQuery or AngularJS. The real question is …

When or where to make an AJAX request?

When creating your app structure and workflow you will have to consider how the data flows in your application:

  • which of the components should be able to send a request to fetch new data?
  • how will the data be passed to other components?
  • will there be more than one action that can result in fetching of the data (loading post details on its page, loading post details in the index page, showing similar posts)?

There are a couple of “best practice” ways to solve the issue of where to call the AJAX requests:

A — componentDidMount

Your component — following our example — <BlogPost/> will receive a prop containing the ID or slug of the article and make the request to load the data. Your app might look something like this:

// App.js
render() {
return (
<div>
<BlogPost id={123} />
</div>
);
}
// BlogPost.js
componentDidMount() {
axios.get(`http://exmaple.com/blog/${this.props.id}`)
.then(response => this.setState(response.data))
}

In response to passing an ID as a prop, the component will send an AJAX request and then in its render() method will check if the data is set in state -if so, render the contents.

While this might appear as a perfectly valid solution it is actually treated as an anti-pattern because we have now promoted the component to a container and tied the presentational element to its implementation, thus decreasing reusability.

UPDATE: This section originally stated that you should use componentWillMount but that’s actually not recommended — all operations that cause side-effects, like ajax calls, should be made in componentDidMount, componentDidUpdate .

B — passing data from parent component via props

Instead of making the <BlogComponent /> a container we will pass all the data directly as props and we will task our parent component with fetching the data. This is mostly done in response to user interaction in the form of URL change with react-router (bonus points for using the onEnter hook of the route).

While I’m using the term parent component here you still have to keep in mind the remark from point A about tying the component to its implementation. You should try to avoid having too many containers / smart components in your application.

C — using a state manager such as flux, redux or mobx

A big help in understanding how the data should / can flow through your application is knowledge of redux or other state-management library (flux, mobx). This is similar to the solution described in example B, but instead of passing the data from parent to child we hold it in a state manager which takes care of setting the props. The data is no longer passed from component to component (we don’t need to manually assign the props — no more grandparent > parent > child >grandchild chains!) but is instead taken directly from the store (think of a store as of a globaly-available singleton object holding all the application state and data — this might sound scary, but be sure to read the documentation of given implementation — I’m oversimplifying things for the sake of keeping this easy for new users).

An added bonus of this solution is the fact that we can call the AJAX request from any place we like (in response to URL change, in componentWillMount, as a response to server-side event sent via socket) and as long as its response is passed to the store our components will update accordingly.

Appendix A — making it look smooth

Now that we know how to load the data from an API, we need to make sure the end user knows something is happening. To do this we can tweak our render() method a bit:

render() {
if(!this.props.title) {
return <Loading />
}
return (
<article>
<h1>{this.props.title}</h1>
</article>
);
}

By checking if we were passed all the props we need we can decide to either show the content of the article or should we inform the user that content is being still loaded. An example implementation of such solution:

Mocking the content while its being loaded

Now, doesn’t that look a lot better? Check out the post titled “Facebook content placeholder deconstruction” to learn how Facebook mocks the post while it’s being loaded. Of course you can just put a spinning wheel there if you like :)

Appendix B — example application

An example application implementing the solution described in point B and the mocking of post while preloading is available on my github account:


* while still an oversimplification, it is a lot closer to truth than calling React an framework