React Query v5 useQuery中initialData与placeholderData的区别及适用场景
React Query v5: 区分useQuery的initialData与placeholderData
核心差异
- 缓存交互:
initialData会被写入Query缓存,相当于给指定queryKey预存了一份有效数据;placeholderData只是临时UI填充值,不会修改缓存内容。 - 加载状态:使用
initialData时,isLoading会直接返回false——因为缓存已有初始数据,组件会优先渲染它,同时后台静默执行queryFn刷新数据;使用placeholderData时,isLoading保持true,因为实际请求仍在进行中。 - 优先级:如果缓存中已有
queryKey对应的有效数据,initialData会被忽略;placeholderData不受缓存状态影响,只要请求处于加载阶段就会生效。
适用场景
- initialData:适合你拥有持久化本地数据(比如localStorage存储的用户信息)、或从父组件传递的已知初始值,希望直接将其作为缓存的起始状态,避免首次加载时的空白UI。
- placeholderData:适合需要临时填充UI的场景(比如模拟列表结构的占位内容、骨架屏替代数据),让用户感知不到加载空白,但最终数据仍依赖请求返回,且不想污染缓存。
实用示例
1. initialData:用本地缓存初始化用户信息
import { useQuery } from '@tanstack/react-query'; const fetchUser = async () => { const res = await fetch('/api/user'); return res.json(); }; function UserProfile() { // 从localStorage读取之前保存的用户数据 const savedUser = JSON.parse(localStorage.getItem('user') || 'null'); const { data: user, isFetching } = useQuery({ queryKey: ['user'], queryFn: fetchUser, initialData: savedUser, }); // 这里isLoading是false,直接渲染本地数据,isFetching表示后台正在刷新 return ( <div> {isFetching && <p>正在刷新用户信息...</p>} <h1>{user.name}</h1> <p>{user.email}</p> </div> ); }
2. placeholderData:列表加载时的临时占位内容
import { useQuery } from '@tanstack/react-query'; const fetchPosts = async () => { const res = await fetch('/api/posts'); return res.json(); }; function PostList() { // 模拟列表结构的临时占位数据 const placeholderPosts = [ { id: 'temp-1', title: '加载中...', content: '请稍候,内容即将加载' }, { id: 'temp-2', title: '加载中...', content: '请稍候,内容即将加载' }, ]; const { data: posts, isLoading } = useQuery({ queryKey: ['posts'], queryFn: fetchPosts, placeholderData: placeholderPosts, }); // isLoading为true,同时渲染占位数据,请求完成后自动替换为真实数据 return ( <ul> {posts.map(post => ( <li key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> </li> ))} </ul> ); }
3. initialData进阶:从其他缓存取初始值
如果需要从另一个Query缓存中获取初始数据,可以用函数形式的initialData:
import { useQuery, useQueryClient } from '@tanstack/react-query'; const fetchUserPosts = async (userId) => { const res = await fetch(`/api/users/${userId}/posts`); return res.json(); }; function UserPosts({ userId }) { const queryClient = useQueryClient(); const { data: posts } = useQuery({ queryKey: ['userPosts', userId], queryFn: () => fetchUserPosts(userId), // 从用户缓存中获取已有的userId,作为初始查询的参数依据 initialData: () => queryClient.getQueryData(['user'])?.posts || [], }); return ( <div> {posts.length > 0 ? ( <ul>{posts.map(post => <li key={post.id}>{post.title}</li>)}</ul> ) : ( <p>暂无帖子</p> )} </div> ); }
内容的提问来源于stack exchange,提问作者Solomon Botchway
相关产品推荐
相关产品推荐

