Compared to frameworks like Angular, React is a library that only comes with functionality for state management and view rendering. With fewer tools baked into it, React requires additional, third-party libraries for handling important client-side features, such as routing, internationalization and sending HTTP requests to remote API endpoints. This unopinionated approach leaves the developer the responsibility of choosing these libraries to pair with React.
For example, imagine you had to integrate an HTTP client library into your React application. You could write the HTTP client library from scratch using a low-level, imperative API like
XMLHttpRequest. However, depending on the amount of time afforded, you might not have enough time to plan and develop the library to account for every possible use case. Alternatively, you could scour the NPM ecosystem for an open-source package that already supports the features you need along with other features you may need in the future. Just typing "http client" into the NPM search bar returns just under three thousand packages.
Picking a specific package over other similar packages boils down to several factors, such as:
Maturity - How old is the package? Is the package used by renowned organizations/companies in their production applications?
Community - Is there an active community committed to the continued development of the package?
Compatibility with Older Browsers - Does the package support older browsers such as Internet Explorer?
Readability and Usability of API - Is the package's API declarative? Is the package's API difficult to grasp?
Feature-Support - Is the package rich with features? Does the package contain features that account for uncommon use cases?
Size/Performance - Does the package increase the bundle size of the application significantly or insignificantly? Was the package written with tree-shaking in mind? Do the utilities/methods provided by the package consume a lot of memory and/or execute quickly?
Error-Handling - Does the package gracefully handle errors? Are error messages helpful in identifying the cause of an issue?
For HTTP client libraries, choosing the Axios library likely makes sense for your React application. It is a popular, promise-based HTTP client with plenty of available configuration options for customizing HTTP requests. Additionally, Axios is isomorphic, which means it can run in both client-side (browser) and server-side (Node.js) environments. With tens of thousands of stargazers on GitHub, Axios's declarative API abstracts away low-level, networking implementation details and allows developers to focus more on the application code.
Below, I'm going to show you how to fetch data in a React application with Axios.
Sending HTTP Requests with
If you decide to use a native browser API to send HTTP requests to a server from your application, then there are two widely-used options:
Many old browsers support the
XMLHttpRequest object, but its imperative API is outdated by modern standards. To make AJAX calls with
XMLHttpRequest, you must:
Instantiate a new
Initialize this object with request options such as HTTP method, URL, etc.
Set up an event listener to capture the response once it is sent back by the server and parsed by the browser.
Send the request to the server.
Since it is not promise-based,
XMLHttpRequest requires a wrapper function to create a promise-based API that utilizes
XMLHttpRequest for the underlying implementation. Below, we wrap
XMLHttpRequest within a
sendRequest wrapper function that returns a promise capable of sending HTTP requests.
That seems like a lot of code just to send an HTTP request! Fortunately, unlike
XMLHttpRequest, the Fetch API is promise-based and boasts a more powerful and flexible feature set. Being promised-based, the Fetch API can make use of ES6
await syntax, which cleans up asynchronous code so it reads as synchronous code.
However, the Fetch API has several downsides:
Because it is a newer browser API, the Fetch API does not support many older browsers and will require a polyfill to recreate its functionality for these non-supporting browsers. In fact, all versions of Internet Explorer are incompatible with the Fetch API.
The Fetch API does not reject on HTTP error statuses (must check
response.statusText) and only rejects the promise on a network failure or if the request failed to complete due to a timeout, etc.
XMLHttpRequest, the Fetch API is not as featureful. For example, it lacks the ability to track upload progress.
Sending HTTP Requests with Axios#
With Axios, not only does it provide a promise-based API, but it also supports older browsers and comes with a plethora of useful features:
Interceptors for Requests and Responses
Automatic Transformation of Request and Response Data
Client-Side Protection Against Cross-Site Request Forgery (CSRF)
Cancellation of Requests
Support for Progress Reports
Under-the-hood, the client-side version of Axios wraps around
XMLHttpRequest while the server-side version of Axios wraps around the
To install Axios, run the following command:
To import Axios into your project:
To send HTTP requests with Axios, pass configuration options to the
axios promise object:
Or for convenience, use the request method alias
Axios automatically provides a request method alias for each HTTP method:
axios.post(url[, data[, config]])
General Request -
configmust specify an HTTP method via the
To use Axios with the
If you need to intercept requests before they are sent or responses before they arrive at the
.catch blocks, then use interceptors:
Of course, we can cover more features of Axios, but this goes beyond the scope of this blog post. If you want to learn more about Axios and its other features, then check out the Axios documentation.
Data Fetching with Axios and React Hooks#
Typically, data-driven React applications fetch data from a server and display this data to the user via an interactive data visualization. Data should be fetched once the component is mounted to the DOM. This allows us to immediately display a loading message to the user informing them to wait patiently as the data is being retrieved. Once the data is retrieved, then the component replaces the loading message with a data visualization.
Render Loading Message →
Fetch Data From Server →
Render Data Visualization
Therefore, within functional components, data fetching should take place within the
useEffect hook, which performs side-effects, such as network requests, similar to the
componentDidUpdate lifecycle methods in class components.
Fetch data with Axios.
Once data has been fetched, set the
datastate variable to this data with the setter function
Regardless of whether or not the data has been fetched or an error has been encountered, set the
isLoadingstate variable to
falsewith the setter function
setIsLoadingto indicate that the component is no longer loading.
Because this data will only be fetched once, the
useEffect hook will be passed an empty dependency array to ensure any state/prop changes don't retrigger the hook and refetch the data again.
useEffect, we define an
async function named
fetchData that uses Axios to fetch data from a server located at a particular URL. Once the server returns the response, destructure out the
data object from the
response object and set the
data state variable to this
data object. If the request fails or times out, then Axios throws an error, which will be handled by the
.catch block. To keep the example short and simple, this
.catch block prints the error to the console of the developer tools. After setting the
data state variable or handling the error, the
isLoading state variable is set to
false, which causes the component to render the
<svg /> element in place of the
<LoadingMessage /> component.
Try using Axios in your next React project!