Data fetching is easy with React Hooks for axios!
Make XMLHttpRequests including all features from axios
Several more nice features:
- Familiar API, axios under the hood
- Request auto-cancellation (concurrent requests or when the component unmounts)
- Cache
- Polling
- Render prop-like API
- Fully typed (TS, Flow is coming)
- Callbacks (
onSuccess
,onError
) to derive state
Using npm:
$ npm install use-axios-request
Using yarn:
$ yarn add use-axios-request
Performing a GET
request
import React from 'react';
import { useAxiosRequest } from 'use-axios-request';
const Avatar = ({ username }) => {
const { isFetching, error, data } = useAxiosRequest(
`https://api.github.com/users/${username}`
);
if (isFetching) {
return 'Loading';
}
if (error) {
return error.message || 'Error';
}
return <img src={data.avatar_url} alt="avatar" />;
};
Performing a POST
request
import React from "react";
import { useAxiosRequest } from "use-axios-request";
const NewIssue = ({ title, body, owner, repo }) => {
const { isFetching, update } = useAxiosRequest();
return (
<button
disabled={isFetching}
onClick={() => {
update({
url: `https://api.github.com/repos/${owner}/${repo}/issues`,
method: 'post',
data: {
title,
body
}
});
}}
>
Submit New Issue
</button>
);
};
import { useAxiosRequest } from 'use-axios-request';
// TypeScript annotation for response data
type DataTypeResponse = {
id: string;
value: string;
};
const Component = () => {
const config = 'https://api.github.com/users/octocat';
// config is just an Axios config that is directly passed to axios() function
// see https://github.com/axios/axios#request-config
// if omitted or null is provided no request is sent
const options = {
// Milliseconds that determine how often should the data with the same config is polled.
// No polling occures if 0 is passed. Defaults to 0.
pollInterval: 0,
// Inspired by "Apollo GraphQL" client https://www.apollographql.com/
// 'no-cache' (default value) - it never returns cached data, it'll always make network request.
// 'cache-first' - it returns cached data OR will make network request.
// 'cache-and-network' - it returns cached data AND will make network request to refresh data.
cache: 'no-cache | cache-first | cache-and-network',
// A Callback that is called after a successful response
onSuccess: () => setShowModal(false),
// A Callback that is called after an error response
onError: () => setShowModal(false),
};
const {
// response.data from latest request
data,
// is currently fetching
isFetching,
// error from latest request
error,
// how many requests have been sent with current config
// it increments if you call refresh or use polling
requestId,
// function that sets a new config and triggers a request
update,
// re-fetch with existing config
refresh,
} = useAxiosRequest<DataTypeResponse>(config, options);
};
config
could be the following types:
- null or undefined
- string (url)
- object (axios config)
useAxiosRequest
triggers a request for every new non-nullable config
. So the code below is buggy.
const MyComponent = props => {
const { data } = useAxiosRequest({
url: '/api',
params: { param1: 'param1' },
});
return <div>{data}</div>;
};
It causes an infinite loop because useAxiosRequest
gets a new object on every render.
You have two options to fix it:
- move the config outside the component
const CONFIG = {
url: '/api',
params: { param1: 'param1' },
};
const MyComponent = props => {
const { data } = useAxiosRequest(CONFIG);
return <div>{data}</div>;
};
- memoize the config if it depends on props
const MyComponent = props => {
const config = React.useMemo(
() => ({
url: '/api',
params: { param1: props.param1 },
}),
[props.param1]
);
const { data } = useAxiosRequest(config);
return <div>{data}</div>;
};
- It's possible to use both
update
method and passing a config as a first argument to the hook in a single component. Keep in mind that usingupdate
method does not make a component re-render the second time while passing a new config as argument does trigger a second render. - If you use both methods simultaneously (
update
and passing a config) you might bump into something like this:
const Component = () => {
const [config, setConfig] = React.useState(
'https://api.github.com/users/octocat'
);
const { update } = useAxiosRequest(config);
// If you click on 'Use update button', a new request is sent.
// Then if you lick on 'Use setConfig', nothing happens
// because literally nothing has changed - you've updated local state
// to the same value as it was before. useAxiosRequest hook remembers
// last passed config as an argument and dispatches a new request only
// if it actually changes.
return (
<div>
<button
onChange={() => update('https://api.github.com/users/Turanchoks')}
>
Use update
</button>
<button
onChange={() => setConfig('https://api.github.com/users/octocat')}
>
Use setConfig
</button>
</div>
);
};
- If you use polling, it's likely that you don't want to show spinner whenever a polling request occurs. You can use
requestId
property which equals1
on the very first request. SoisFetching && requestId === 1
istrue
when it's a initial request.
MIT