When you start asking about AJAX and React, the first thing the experts will tell you is that React is a view library and React has no networking/AJAX features.
It's good to know, but not very helpful when you just want to get data from the server into your React components.
The truth is, there are a ton of ways to do it. You probably have thought of a couple ways yourself, but if you choose the wrong way, your code could get messy.
So you're left wondering: what is the 'right' or 'preferred' way?
What is the best practice for getting server data into React components?
And the answer is.... it depends.
I've collected four good ways to use AJAX with React.
Which approach you use depends on the size and complexity of your app, along with which libraries or technologies you are already using.
These are your options:
This is the simplest approach so it's great for prototypes and small apps.
With this approach, you build a single root/parent component that issues all
your AJAX requests. The root component stores the AJAX response data in it's
state
, and passes that state (or a portion of it) down to child components as
props.
For an example of this approach take a look at the
official React tutorial.
The CommentBox
component is the root component that sends all the AJAX
requests.
The thing I don't like about the official tutorial: they are using jQuery to send AJAX requests. jQuery is a large library with many features, so using it just for AJAX doesn't make sense.
I recommend using fetch()
. It is a simple, standardized, JavaScript AJAX API.
It is already supported by Chrome and Firefox, and polyfills are available for
node and other browsers. For details, or for help choosing your own AJAX
library, see my AJAX library comparison.
Another caveat: if you have a deep component tree (subcomponents of subcomponents of subcomponents...) then you will have to pass data a long way from the root component to your deeper components.
When to use a root component:
A container component "provides the data and behavior to presentational or other container components." If you haven't heard the term yet, I suggest Dan Abramov's article on presentational and container components.
For our purposes, the container component approach is just like the root component approach, except with multiple components that can interact with the server.
Here's how it works: for every presentational component that needs data from the server, create a container component that sends AJAX requests to get that data, and provides it to the child component via props.
As a concrete example, imagine you want to display a user profile with a name and a picture.
First build a <UserProfile />
presentational component that accepts a name
and a profileImage
prop. This component should not have any AJAX code.
Then build a <UserProfileContainer />
component that accepts a userId
. It
downloads the data for that particular user, and passes it to <UserProfile />
via props.
The AJAX requests in the container components can be sent with a simple AJAX library. I recommend fetch().
When to use container components for AJAX:
Redux manages data, and AJAX provides data from the server, so it makes sense that your Redux code should be handling your network requests.
If you are using Redux, don't put AJAX in your React components. Instead, put it in your Async Actions.
I recommend using fetch() to make the actual network requests, and luckily, that's also what Redux uses in their official documentation. They've even written an example reddit API that uses Redux, React, and fetch().
If you are using another flux, the approach is similar - send network requests in your actions.
When to use a Redux Async Actions:
With Relay, you declare the data needs of your React components with GraphQL, and Relay automatically downloads that data and fills out the component props.
Relay works great for large applications, but requires a large up-front time investment. You need to:
Relay is only meant to communicate with GraphQL servers, so it won't help you communicate with any 3rd party APIs.
Currently, Relay can only communicate with a single GraphQL server, so if you are getting data from multiple sources, this approach is not for you. The ability to communicate with multiple servers will likely be added in the future, it is discussed deep in this github issue.
If you're going with this approach, the Relay Playground is a great place to start figuring out how Relay works.
When to use Relay:
If all of the above ways are correct, then which ways aren't correct? Here are 2 common approaches that I suggest avoiding.
Don't add AJAX logic to a component that is already responsible for something else - like complex interface rendering. Doing so would violate the separation of concerns design principle.
You could have AJAX logic living outside of React entirely and call ReactDOM.render() whenever you receive an update from the server.
This approach might work okay. I list it as an antipattern because I believe the root component approach is similar, but cleaner.
Applications built with React are modular. React is just one of the modules. The AJAX library is another. This isn't Rails or Angular.
You might sometimes need help figuring out what the other modules are and how they fit together.
What's the best library for X? and How do I use React with Y? - These are the kinds of questions you'll see answered on this blog - with regular new posts.