Next.js React Query
外观
Next.js React Query[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
React Query 是一个用于管理服务器状态的强大库,专为 React 应用设计。在 Next.js 中,它能够高效地处理数据获取、缓存、同步和更新,同时减少样板代码。React Query 的核心优势在于其智能缓存机制和自动后台刷新功能,使得开发者可以专注于业务逻辑而非数据管理细节。
在 Next.js 中,React Query 通常与静态生成(SSG)、服务器端渲染(SSR)或客户端渲染(CSR)结合使用,提供灵活的数据加载策略。它支持:
- 自动缓存和重复请求去重
- 后台数据刷新
- 分页和无限加载优化
- 错误处理和重试机制
核心概念[编辑 | 编辑源代码]
QueryClient 与 QueryClientProvider[编辑 | 编辑源代码]
React Query 的核心是 QueryClient
,它管理所有查询的状态和缓存。在 Next.js 中,通常需要在应用顶层初始化并注入它:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App({ Component, pageProps }) {
return (
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
);
}
基本查询(useQuery)[编辑 | 编辑源代码]
useQuery
是用于获取数据的核心钩子。以下是一个获取用户数据的示例:
import { useQuery } from '@tanstack/react-query';
function UserProfile({ userId }) {
const { data, isLoading, error } = useQuery({
queryKey: ['user', userId], // 唯一标识查询的键
queryFn: () => fetch(`/api/users/${userId}`).then(res => res.json()),
staleTime: 5000, // 数据在5秒后视为过期
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{data.name}</div>;
}
修改数据(useMutation)[编辑 | 编辑源代码]
useMutation
用于创建、更新或删除数据:
import { useMutation } from '@tanstack/react-query';
function AddUser() {
const mutation = useMutation({
mutationFn: (newUser) => fetch('/api/users', {
method: 'POST',
body: JSON.stringify(newUser),
}),
onSuccess: () => {
// 用户添加成功后的操作
},
});
return (
<button onClick={() => mutation.mutate({ name: 'New User' })}>
Add User
</button>
);
}
高级特性[编辑 | 编辑源代码]
预加载数据[编辑 | 编辑源代码]
在 Next.js 中,可以在页面加载前预取数据:
// 在 getServerSideProps 或 getStaticProps 中
export async function getServerSideProps() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
});
return { props: { dehydratedState: dehydrate(queryClient) } };
}
// 在客户端通过 useQuery 直接使用预加载的数据
const { data } = useQuery({ queryKey: ['posts'], queryFn: fetchPosts });
无限查询[编辑 | 编辑源代码]
对于分页或无限加载的场景:
import { useInfiniteQuery } from '@tanstack/react-query';
function Posts() {
const {
data,
fetchNextPage,
hasNextPage,
} = useInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam = 1 }) => fetchPosts(pageParam),
getNextPageParam: (lastPage) => lastPage.nextPage,
});
return (
<>
{data.pages.map((page) => (
page.posts.map(post => <Post key={post.id} {...post} />)
))}
<button onClick={() => fetchNextPage()}>
{hasNextPage ? 'Load More' : 'Nothing more to load'}
</button>
</>
);
}
实际案例[编辑 | 编辑源代码]
电商产品列表[编辑 | 编辑源代码]
假设构建一个电商网站的产品列表页:
function ProductList() {
const { data: products, isLoading } = useQuery({
queryKey: ['products'],
queryFn: () => fetch('/api/products').then(res => res.json()),
// 产品数据每60秒自动刷新
staleTime: 60000,
});
const { mutate: addToCart } = useMutation({
mutationFn: (productId) => addProductToCart(productId),
onSuccess: () => showToast('Added to cart!'),
});
if (isLoading) return <Spinner />;
return (
<div className="grid">
{products.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={() => addToCart(product.id)}
/>
))}
</div>
);
}
性能优化[编辑 | 编辑源代码]
React Query 提供多种优化选项:
1. 选择性重渲染:只有数据变化的组件会重新渲染 2. 智能缓存:相同查询的多个实例共享缓存 3. 请求合并:同时发起的相同请求会自动合并 4. 垃圾回收:未使用的缓存数据会被自动清理
常见问题[编辑 | 编辑源代码]
与 Next.js 缓存如何协作?[编辑 | 编辑源代码]
React Query 的客户端缓存可以与 Next.js 的服务器端缓存(如 getStaticProps
)完美配合。初始加载使用服务器数据,后续导航使用客户端缓存。
如何处理认证?[编辑 | 编辑源代码]
可以通过配置 QueryClient
的默认选项全局处理认证错误:
const queryClient = new QueryClient({
defaultOptions: {
queries: {
onError: (error) => {
if (error.status === 401) redirectToLogin();
},
},
},
});
总结[编辑 | 编辑源代码]
React Query 为 Next.js 应用提供了专业的数据管理解决方案,具有以下优势:
- 减少约 80% 的数据管理样板代码
- 内置智能缓存和性能优化
- 与 Next.js 的渲染模式深度集成
- 丰富的开发者工具支持
通过合理配置,可以构建出既快速又可靠的数据驱动型应用。