axios-hooks、react-query、swr、use-http は、React アプリケーションでサーバーとの通信やデータ管理を簡単にするためのライブラリです。これらは、HTTP リクエストの送信、キャッシュ管理、ローディング状態の処理、エラーハンドリングなどを抽象化し、開発者が UI の構築に集中できるように支援します。react-query(現在は TanStack Query)と swr は包括的なキャッシュ戦略とサーバー状態管理を提供しますが、axios-hooks と use-http はよりシンプルで、特定の HTTP クライアントや基本的なフックに特化しています。
React アプリケーションでサーバーデータを扱う際、axios-hooks、react-query、swr、use-http は代表的な選択肢です。これらはすべて HTTP リクエストを簡単にするものですが、キャッシュの仕組み、機能の豊富さ、そしてメンテナンス方針に大きな違いがあります。実務でどれを選ぶべきか、技術的な観点から比較します。
各ライブラリは、データ取得のためのフックを提供していますが、その引数や返り値の形式が異なります。
react-query は、クエリキーと関数をオブジェクトで渡します。
@tanstack/react-query ですが、ここでは react-query として説明します。// react-query
import { useQuery } from '@tanstack/react-query';
function UserProfile() {
const { data, isLoading } = useQuery({
queryKey: ['user', 1],
queryFn: () => fetch('/api/user/1').then(res => res.json())
});
if (isLoading) return <div>Loading...</div>;
return <div>{data.name}</div>;
}
swr は、キーとフェッチャー関数を引数に取ります。
// swr
import useSWR from 'swr';
function UserProfile() {
const { data, isLoading } = useSWR('/api/user/1', fetcher);
if (isLoading) return <div>Loading...</div>;
return <div>{data.name}</div>;
}
axios-hooks は、Axios の設定オブジェクトをそのまま渡します。
// axios-hooks
import useAxios from 'axios-hooks';
function UserProfile() {
const [{ data, loading }, refetch] = useAxios('/api/user/1');
if (loading) return <div>Loading...</div>;
return <div>{data.name}</div>;
}
use-http は、HTTP メソッドごとに専用のフックを用意しています。
useGet、usePost など、目的が明確で直感的です。// use-http
import { useGet } from 'use-http';
function UserProfile() {
const { data, loading } = useGet('/api/user/1');
if (loading) return <div>Loading...</div>;
return <div>{data.name}</div>;
}
データ取得ライブラリを選ぶ際、最も重要なのが「キャッシュをどう扱うか」です。
react-query は、クエリキーに基づいてデータをキャッシュします。
// react-query: キャッシュ設定
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 1000 * 60, // 1 分間は新鮮とみなす
gcTime: 1000 * 60 * 5 // 5 分間キャッシュを保持
});
swr は、stale-while-revalidate 戦略を採用しています。
// swr: 再検証設定
useSWR('/api/todos', fetcher, {
revalidateOnFocus: true, // フォーカス時に再取得
dedupingInterval: 2000 // 2 秒間は重複リクエストを防ぐ
});
axios-hooks は、デフォルトではキャッシュしません。
useCache オプションを有効にする必要があります。react-query や swr よりも単純です。// axios-hooks: キャッシュ有効化
useAxios({
url: '/api/todos',
method: 'GET'
}, { useCache: true });
use-http は、基本的なキャッシュ機能を提供します。
// use-http: キャッシュ設定
useGet('/api/todos', { cache: true });
POST や PUT などの書き込み処理も、ライブラリごとにアプローチが違います。
react-query は useMutation を提供します。
// react-query
const mutation = useMutation({
mutationFn: postData,
onSuccess: () => queryClient.invalidateQueries(['todos'])
});
swr は mutate 関数を使用します。
useSWRMutation も利用可能です(追加パッケージ)。// swr
import { mutate } from 'swr';
async function updateTodo() {
await fetch('/api/todos', { method: 'POST' });
mutate('/api/todos'); // キャッシュを更新
}
axios-hooks は、通常の Axios インスタンスを使います。
refetch 関数で再取得をトリガーできます。// axios-hooks
const [{ loading }, refetch] = useAxios('/api/todos');
async function updateTodo() {
await axios.post('/api/todos', data);
refetch(); // 再取得
}
use-http は usePost などのフックを使います。
// use-http
const { post, loading } = usePost('/api/todos');
async function updateTodo() {
await post({ title: 'New' });
}
ライブラリの将来性を考えることも重要です。
react-query は、現在は TanStack という組織によって管理されています。
swr は、Vercel によって维护されています。
axios-hooks は、コミュニティによって维护されています。
use-http は、小規模なライブラリです。
| 機能 | react-query | swr | axios-hooks | use-http |
|---|---|---|---|---|
| キャッシュ | ⭐⭐⭐ 高度 | ⭐⭐ 標準 | ⭐ 基本 | ⭐ 基本 |
| Mutation | ⭐⭐⭐ 専用フック | ⭐⭐ 関数/フック | ❌ 手動 | ⭐⭐ 専用フック |
| HTTP クライアント | 任意 (fetch/axios) | 任意 (fetch/axios) | 🔒 Axios | 任意 (fetch/axios) |
| DevTools | ✅ あり | ❌ なし | ❌ なし | ❌ なし |
| 学習コスト | 中 | 低 | 低 | 低 |
react-query は、機能性と拡張性を求める本格的なプロジェクトに最適です — 特にチーム開発や大規模アプリケーションでは、その構造の明確さが役立ちます。
swr は、シンプルさと速度を重視する場合に選ばれます — Next.js を使っている場合や、設定を減らしてすぐに始めたい時に適しています。
axios-hooks は、Axios に強く依存している既存プロジェクトで、最小の変更でフックを導入したい時に有用です — ただし、キャッシュ管理は自分で補う必要があります。
use-http は、小規模なツールやプロトタイプで、とにかく早く書きたい時に使えます — 長期的なメンテナンスを考えると、react-query か swr への移行を検討するべき場面も出てきます。
最終的には、プロジェクトの規模と、データ同期にどれだけの労力を割けるかで判断しましょう — 単純な取得なら軽量なものを、複雑な状態管理なら react-query が安心です。
axios-hooks は、既存の Axios 設定(インターセプターやインスタンス)をそのまま活用したい場合に適しています。キャッシュ機能は限定的ですが、Axios の機能全体を使いたいプロジェクトで、リクエストキャンセルなどの基本的な管理をフックで行いたい時に選択します。
react-query(TanStack Query)は、大規模で複雑なアプリケーションに最適です。強力なキャッシュ管理、バックグラウンド更新、mutation 処理、DevTools などを必要とする場合、このライブラリが業界標準となります。長期的なメンテナンス性とエコシステムの豊かさを重視する際に選定します。
swr は、シンプルさとパフォーマンスを重視するプロジェクトに向いています。Vercel によって维护されており、stale-while-revalidate 戦略に基づいた軽量なキャッシュ機能を提供します。設定を最小限に抑えつつ、効率的なデータ取得を実現したい場合に選択します。
use-http は、非常にシンプルな REST API 接続が必要な場合に適しています。useGet や usePost などの直感的なフックを提供しますが、高度なキャッシュや状態管理機能は期待できません。小規模なプロジェクトや、プロトタイプ作成時に検討します。
The license of this software has changed to AWISC - Anti War ISC license
React hooks for axios, with built-in support for server side rendering.
npm install axios axios-hooks
axiosis a peer dependency and needs to be installed explicitly
[email protected] is compatible with [email protected][email protected] and below are compatible with [email protected]import useAxios from 'axios-hooks'
function App() {
const [{ data, loading, error }, refetch] = useAxios(
'https://reqres.in/api/users?delay=1'
)
if (loading) return <p>Loading...</p>
if (error) return <p>Error!</p>
return (
<div>
<button onClick={refetch}>refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
}
The package exports one default export and named exports:
import useAxios, {
configure,
loadCache,
serializeCache,
makeUseAxios
} from 'axios-hooks'
The main React hook to execute HTTP requests.
url|config - The request URL or config object, the same argument accepted by axios.options - An options object.
manual ( false ) - If true, the request is not executed immediately. Useful for non-GET requests that should not be executed when the component renders. Use the execute function returned when invoking the hook to execute the request manually.useCache ( true ) - Allows caching to be enabled/disabled for the hook. It doesn't affect the execute function returned by the hook.ssr ( true ) - Enables or disables SSR supportautoCancel ( true ) - Enables or disables automatic cancellation of pending requests whether it be
from the automatic hook request or from the manual execute method[!IMPORTANT]
Default caching behavior can interfere with test isolation. Read the testing section for more information.
Returns
[{ data, loading, error, response }, execute, manualCancel]
data - The success response data property (for convenient access).
loading - True if the request is in progress, otherwise False.
error - The error value
response - The whole success response object.
execute([config[, options]]) - A function to execute the request manually, bypassing the cache by default.
config - Same config object as axios, which is shallow-merged with the config object provided when invoking the hook. Useful to provide arguments to non-GET requests.options - An options object.
useCache ( false ) - Allows caching to be enabled/disabled for this "execute" function.Returns
A promise containing the response. If the request is unsuccessful, the promise rejects and the rejection must be handled manually.
manualCancel() - A function to cancel outstanding requests manually.
Allows to provide custom instances of cache and axios and to override the default options.
cache An instance of lru-cache, or false to disable the cacheaxios An instance of axiosdefaultOptions An object overriding the default Hook options. It will be merged with the default options.Dumps the request-response cache, to use in server side rendering scenarios.
Returns
Promise<Array> A serializable representation of the request-response cache ready to be used by loadCache
Populates the cache with serialized data generated by serializeCache.
cache The serializable representation of the request-response cache generated by serializeCacheCreates an instance of the useAxios hook configured with the supplied cache, axios instance and default options.
cache An instance of lru-cache, or false to disable the cacheaxios An instance of axiosdefaultOptions An object overriding the default Hook options. It will be merged with the default options.Returns
An instance of useAxios React Hook which will always use the provided cache and axios instance.
The returned value, besides being a function that can be used as a React Hook, also contains the properties:
resetConfigureconfigureloadCacheserializeCachewhich are the same as the package's named exports but limited to the useAxios instance returned by makeUseAxios.
The arguments provided to useAxios(config[,options]) are watched for changes and compared using deep object comparison.
When they change, if the configuration allows a request to be fired (e.g. manual:false), any pending request is canceled and a new request is triggered, to avoid automatic cancellation you should use autoCancel:false option
Because of this, it's important to make sure that the arguments to useAxios preserve deep equality across component renders. This is often the case unless functions (e.g. axios transformers) are provided to a configuration object. In that case, those functions need to be memoized or they will trigger a request execution at each render, leading to an infinite loop.
Unless provided via the configure function, axios-hooks uses as defaults:
axios - the default axios package exportcache - a new instance of the default lru-cache package export, with no argumentsdefaultOptions - { manual: false, useCache: true, ssr: true, autoCancel: true }These defaults may not suit your needs, for example:
In such cases you can use the configure function to provide your custom implementation of both.
When
configureis used, it should be invoked once before any usages of theuseAxioshook
import { configure } from 'axios-hooks'
import LRU from 'lru-cache'
import Axios from 'axios'
const axios = Axios.create({
baseURL: 'https://reqres.in/api'
})
const cache = new LRU({ max: 10 })
configure({ axios, cache })
On the client, requests are executed when the component renders using a React useEffect hook.
This may be undesirable, as in the case of non-GET requests. By using the manual option you can skip the automatic execution of requests and use the return value of the hook to execute them manually, optionally providing configuration overrides to axios.
In the example below we use the useAxios hook twice. Once to load the data when the component renders, and once to submit data updates via a PUT request configured via the manual option.
import useAxios from 'axios-hooks'
function App() {
const [{ data: getData, loading: getLoading, error: getError }] = useAxios(
'https://reqres.in/api/users/1'
)
const [{ data: putData, loading: putLoading, error: putError }, executePut] =
useAxios(
{
url: 'https://reqres.in/api/users/1',
method: 'PUT'
},
{ manual: true }
)
function updateData() {
executePut({
data: {
...getData,
updatedAt: new Date().toISOString()
}
})
}
if (getLoading || putLoading) return <p>Loading...</p>
if (getError || putError) return <p>Error!</p>
return (
<div>
<button onClick={updateData}>update data</button>
<pre>{JSON.stringify(putData || getData, null, 2)}</pre>
</div>
)
}
The cancellation method can be used to cancel an outstanding request whether it be
from the automatic hook request or from the manual execute method.
In the example below we use the useAxios hook with its automatic and manual requests.
We can call the cancellation programmatically or via controls.
function App() {
const [pagination, setPagination] = useState({})
const [{ data, loading }, refetch, cancelRequest] = useAxios({
url: '/users?delay=5',
params: { ...pagination }
})
const handleFetch = () => {
setPagination({ per_page: 2, page: 2 })
}
const externalRefetch = async () => {
try {
await refetch()
} catch (e) {
// Handle cancellation
}
}
return (
<div>
<button onClick={handleFetch}>refetch</button>
<button onClick={externalRefetch}>External Refetch</button>
<button disabled={!loading} onClick={cancelRequest}>
Cancel Request
</button>
{loading && <p>...loading</p>}
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
}
axios-hooks seamlessly supports server side rendering scenarios, by preloading data on the server and providing the data to the client, so that the client doesn't need to reload it.
useAxios HTTP requests are executed on the serverserializeCache() in order to obtain a serializable representation of the request-response cachewindow global variableloadCache<!-- fragment of the HTML template defining the window global variable -->
<script>
window.__AXIOS_HOOKS_CACHE__ = {{{cache}}}
</script>
// server code for the server side rendering handler
import { serializeCache } from 'axios-hooks'
router.use(async (req, res) => {
const index = fs.readFileSync(`${publicFolder}/index.html`, 'utf8')
const html = ReactDOM.renderToString(<App />)
// wait for axios-hooks HTTP requests to complete
const cache = await serializeCache()
res.send(
index
.replace('{{{html}}}', html)
.replace('{{{cache}}}', JSON.stringify(cache).replace(/</g, '\\u003c'))
)
})
// client side code for the application entry-point
import { loadCache } from 'axios-hooks'
loadCache(window.__AXIOS_HOOKS_CACHE__)
delete window.__AXIOS_HOOKS_CACHE__
ReactDOM.hydrate(<App />, document.getElementById('root'))
Sometimes it is necessary to communicate with different APIs or use different caching strategies for different HTTP interactions.
makeUseAxios allows to create multiple instances of the useAxios React Hook which can be configured and managed independently.
In other words, makeUseAxios is a factory of useAxios, which returns a React Hook configured against the provided axios or cache instances.
This feature can also be used to create a single pre configured React Hook instance as an alternative to the global
configurefeature
import axios from 'axios'
import { makeUseAxios } from 'axios-hooks'
const useAxios = makeUseAxios({
axios: axios.create({ baseURL: 'https://reqres.in/api' })
})
function App() {
const [{ data, loading, error }, refetch] = useAxios('/users?delay=1')
if (loading) return <p>Loading...</p>
if (error) return <p>Error!</p>
return (
<div>
<button onClick={refetch}>refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
}
Testing components that make use of the useAxios hook are susceptible to test isolation leakage because of default caching behavior. The following snippets can be used to disable caching while testing:
beforeAll(() => {
useAxios.configure({ cache: false })
})
axios-hooks depends on a native ES6 Promise implementation to be supported. If your environment doesn't support ES6 Promises, you can polyfill.
axios-hooks is heavily inspired by graphql-hooks,
developed by the awesome people at NearForm.
MIT