Reaching Out To The Web
HTTP Requests in React
npm install axios
and import it:import axios from "axios";
.Create a
Promise
object usingaxios.get
,axios.post
, etc.Chain
.then()
and.catch()
for handlingresponse
anderror
respectively.
Adding Interceptors
It's very common to handle errors and HTTP requests locally within a component. For example, a component may have a this.state.error
to track if something breaks during a .catch()
. Then, the UI will render a message to the user if this.state.error
has content.
However, on top of local HTTP request and error handling, you can use interceptors that add global customization to your HTTP requests and errors.
Think of interceptors as middle men that are passed the request
, response
, or error
object to do custom work. Then you pass the objects forward for local handling.
// In a global file like index.js, add this...
// ** FOR REQUESTS **
const reqInterceptor = axios.interceptors.request.use(request => {
// Do something before request is sent
// COMMON PRACTICE: Add authorization headers
return request; // pushes forward request for local handling
}, error => {
// Do something with error
return Promise.reject(error); // pushes forwards error for local handling
});
// ** FOR RESPONSES **
const resInterceptor = axios.interceptors.response.use(response => {
// Do something with response data
return response; // pushes forward response for local handling
}, error => {
// Do something with error
return Promise.reject(error); // pushes forwards error for local handling
});
Removing Interceptors
To eject/remove an interceptor, simply use:
const reqInterceptor = axios.interceptors.request.use(...)
const resInterceptor = axios.interceptors.response.use(...)
// ** TO EJECT INTERCEPTOR **
axios.interceptors.request.eject(reqInterceptor);
axios.interceptors.response.eject(resInterceptor);
Note: It's a good idea to add eject
as part of a cleanup function like componentWillUnmount
or the cleanup callback in useEffect
.
Global Configuration
axios
and other request libraries give you access to a defaults
object for configuring defaults.
// In a global file like index.js...
axios.defaults.baseURL = "https://api.com/v1"; // Base URL for API endpoint
axios.defaults.headers.common // For headers that apply to all requests
axios.defaults.headers.post // For headers specifically for POST requests
Axios Instances
Sometimes your axios
configuration needs to be different for different situations. For this, you can set up half measures known as an instance.
import axios from "axios";
const axiosInstance = axios.create({
baseURL: "https://api.com/v2"
});
// axiosInstance.interceptors works too
// axiosInstance.defaults works too
export default axiosInstance;
Now you can use axiosInstance
for HTTP requests and even create multiple instances.
Pro tip: Instances work because of prototypal inheritance! You're overriding default behaviour in the global axios
object. If you don't override, axiosInstance
will inherit axios
properties.
Error Handling HOC
Using interceptors, we can create a higher-order component that handles any axios
errors and displays them. Here's the basic code:
const withErrorHandler = (WrappedComponent, axios) => {
return props => {
// Create error state
const [error, setError] = useState(null)
// On mount, add axios interceptors to axios instance USED BY WrappedComponent
useEffect(() => {
axios.interceptors.request.use(req => {
setError(null) // <= Reset error state on new request
return req
})
axios.interceptors.response.use(res => res, err => {
setError(err) // <= Set error state
return Promise.reject(err)
})
}, [setError])
return (
<>
<Modal {/* <= We're using a modal to display the error */}
show={error ? true : false}
>
{error ? error.message : null}
<Modal />
<WrappedComponent {...props} /> {/* <= Passing props down to component */}
</>
)
}
}
Then in your actual component, add the HOC:
export default withErrorHandler(MyComponent, axios)
Last updated