Framer Motion完全ガイド 2025 - Reactアニメーションライブラリの決定版
Framer Motion(現Motion)を徹底解説。基本的なアニメーションから高度なジェスチャー、スクロール連動、レイアウトアニメーションまで、2025年最新機能を含む実践的な実装方法とベストプラクティスを完全網羅します。
ReactアプリケーションのデータフェッチングとキャッシュManagementを劇的に改善するSWRとTanStack Queryを徹底比較。パフォーマンス、機能、使いやすさ、エコシステムの観点から、プロジェクトに最適な選択を解説します。
2025 年の Reactアプリケーション開発において、効率的なデータフェッチングとキャッシュ管理は不可欠です。SWRとTanStack Query(旧 React Query)は、この分野をリードする 2 つのライブラリです。本記事では、両者の特徴を徹底比較し、プロジェクトに最適な選択を支援します。
ローディング、エラー、データの管理が複雑
効率的なキャッシュ戦略の実装が困難
データの同期とバックグラウンド更新
SWRとTanStack Queryが主流に
両ライブラリが業界標準として定着
特徴 | SWR | TanStack Query | 違い |
---|---|---|---|
開発元 | Vercel(Next.js) | Tanner Linsley | 企業 vs 個人主導 |
初回リリース | 2019年 | 2019年 | 同時期 |
バンドルサイズ | ~13KB | ~20KB | SWRが軽量 |
依存関係 | なし | なし | 両者ともゼロ依存 |
学習曲線 | 低い | 中程度 | SWRがシンプル |
機能の豊富さ | 必要十分 | 非常に豊富 | TanStack Queryが高機能 |
SWR は”stale-while-revalidate”戦略に基づき、シンプルで直感的な API を提供します。
import useSWR from 'swr';
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher);
if (error) return <div>エラーが発生しました</div>;
if (isLoading) return <div>読み込み中...</div>;
return <div>こんにちは、{data.name}さん!</div>;
}
TanStack Query は、より包括的なソリューションを提供し、複雑なユースケースに対応します。
import { useQuery } from '@tanstack/react-query';
function Profile() {
const { data, error, isLoading } = useQuery({
queryKey: ['user'],
queryFn: fetchUser,
staleTime: 5 * 60 * 1000, // 5分
gcTime: 10 * 60 * 1000, // 10分(旧cacheTime)
});
if (error) return <div>エラー: {error.message}</div>;
if (isLoading) return <div>読み込み中...</div>;
return <div>こんにちは、{data.name}さん!</div>;
}
チャートを読み込み中...
// SWRのミューテーション
import useSWRMutation from 'swr/mutation';
function UpdateProfile() {
const { trigger, isMutating } = useSWRMutation(
'/api/user',
async (url, { arg }) => {
const res = await fetch(url, {
method: 'PUT',
body: JSON.stringify(arg)
});
return res.json();
}
);
const handleUpdate = async (data) => {
try {
await trigger(data);
// 成功時の処理
} catch (e) {
// エラー処理
}
};
return (
<button onClick={() => handleUpdate({ name: '新しい名前' })}>
更新 {isMutating && '中...'}
</button>
);
}
// TanStack Queryのミューテーション
import { useMutation, useQueryClient } from '@tanstack/react-query';
function UpdateProfile() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (data) => {
return fetch('/api/user', {
method: 'PUT',
body: JSON.stringify(data)
}).then(r => r.json());
},
onSuccess: (data) => {
// キャッシュの更新
queryClient.setQueryData(['user'], data);
// または再フェッチ
queryClient.invalidateQueries({ queryKey: ['user'] });
},
onError: (error) => {
console.error('更新エラー:', error);
}
});
return (
<button onClick={() => mutation.mutate({ name: '新しい名前' })}>
更新 {mutation.isPending && '中...'}
</button>
);
}
SWRの特徴:
mutate
関数での直接的なキャッシュ操作TanStack Queryの特徴:
onSuccess
、onError
などのライフサイクルフック使い分け:
// SWRでのリアルタイム更新
function LiveData() {
const { data, mutate } = useSWR('/api/live-data', fetcher, {
refreshInterval: 1000, // 1秒ごとにポーリング
});
// WebSocketとの統合
useEffect(() => {
const ws = new WebSocket('wss://api.example.com/live');
ws.onmessage = (event) => {
const newData = JSON.parse(event.data);
mutate(newData, false); // キャッシュを更新(再検証なし)
};
return () => ws.close();
}, [mutate]);
return <div>{data?.value}</div>;
}
// TanStack Queryでのリアルタイム更新
function LiveData() {
const queryClient = useQueryClient();
const { data } = useQuery({
queryKey: ['live-data'],
queryFn: fetchLiveData,
refetchInterval: 1000, // 1秒ごとにポーリング
});
// WebSocketとの統合
useEffect(() => {
const ws = new WebSocket('wss://api.example.com/live');
ws.onmessage = (event) => {
const newData = JSON.parse(event.data);
queryClient.setQueryData(['live-data'], newData);
};
return () => ws.close();
}, [queryClient]);
return <div>{data?.value}</div>;
}
フレームワーク | SWR | TanStack Query | 備考 |
---|---|---|---|
Next.js | ◎ ネイティブ | ○ 良好 | SWRはVercel製 |
Remix | ○ 良好 | ◎ 推奨 | Remixドキュメントで推奨 |
Gatsby | ○ 良好 | ○ 良好 | 両方とも問題なし |
React Native | ○ 良好 | ◎ 優秀 | TanStack Queryが充実 |
Vue/Svelte | ✗ 非対応 | ◎ 対応 | TanStackは多フレームワーク対応 |
TanStack Query DevTools は、より包括的なデバッグ体験を提供します:
// TanStack Query DevToolsの設定
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
// SWR - 必要な機能のみインポート
import useSWR from 'swr';
import useSWRMutation from 'swr/mutation';
import useSWRInfinite from 'swr/infinite';
// TanStack Query - モジュラーインポート
import { useQuery } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';
import { useInfiniteQuery } from '@tanstack/react-query';
// SWRのキャッシュ戦略
const { data } = useSWR(key, fetcher, {
// キャッシュの設定
dedupingInterval: 2000, // 2秒間は重複リクエストを防ぐ
focusThrottleInterval: 5000, // フォーカス時の再検証を5秒に1回に制限
// 再検証の設定
revalidateIfStale: true,
revalidateOnMount: true,
revalidateOnFocus: true,
revalidateOnReconnect: true,
// エラーハンドリング
shouldRetryOnError: true,
errorRetryInterval: 5000,
errorRetryCount: 3,
// パフォーマンス
suspense: false,
keepPreviousData: true,
});
// グローバル設定
import { SWRConfig } from 'swr';
<SWRConfig value={{
refreshInterval: 3000,
fetcher: (url) => fetch(url).then(res => res.json()),
onError: (error, key) => {
console.error(`SWRエラー ${key}:`, error);
}
}}>
<App />
</SWRConfig>
// TanStack Queryのキャッシュ戦略
const { data } = useQuery({
queryKey: ['todos', filters],
queryFn: fetchTodos,
// キャッシュの設定
staleTime: 5 * 60 * 1000, // 5分間は新鮮とみなす
gcTime: 10 * 60 * 1000, // 10分後にガベージコレクション
// 再フェッチの設定
refetchOnMount: true,
refetchOnWindowFocus: true,
refetchOnReconnect: true,
refetchInterval: false,
// エラーハンドリング
retry: 3,
retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
// パフォーマンス
structuralSharing: true,
networkMode: 'offlineFirst',
});
// グローバル設定
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
retry: 3,
},
},
});
共通のベストプラクティス:
適切なキャッシュ時間の設定
エラーハンドリング
ネットワーク最適化
メモリ管理
チャートを読み込み中...
SWRが最適な場合:
TanStack Queryが最適な場合:
// 移行前(SWR)
const { data, error, mutate } = useSWR('/api/user', fetcher);
// 移行後(TanStack Query)
const { data, error, refetch } = useQuery({
queryKey: ['user'],
queryFn: () => fetcher('/api/user'),
});
// 移行ヘルパー関数
function useSWRCompat(key, fetcher, options = {}) {
const query = useQuery({
queryKey: Array.isArray(key) ? key : [key],
queryFn: () => fetcher(key),
refetchInterval: options.refreshInterval,
enabled: key !== null,
});
return {
data: query.data,
error: query.error,
isLoading: query.isLoading,
mutate: query.refetch,
};
}
TanStack Query は単なるデータフェッチングライブラリではありません。 非同期状態管理の完全なソリューションです。
SWR と TanStack Query は、どちらも優れたデータフェッチングライブラリです。選択の際は以下を考慮してください:
最終的に、両ライブラリとも本番環境で実績があり、活発にメンテナンスされています。プロジェクトの要件に最も適したものを選択することが成功への鍵となります。