在SWR中,Patch请求成功后如何结合分页查询参数实现数据更新?并如何获取当前数据的分页页码?
解决SWR分页场景下Patch后的缓存更新问题
我完全懂你碰到的麻烦——SWR的mutate是严格匹配缓存键(也就是请求数据时用的URL)的,你之前固定用api/users?page=1&limit=10去更新缓存,自然在第2页的时候不会生效,因为当前页的缓存键是api/users?page=2&limit=10。下面分两步帮你解决问题:
1. 获取当前页面的分页参数
首先得拿到当前页面的page和limit参数,这取决于你用的路由方案:
如果你用Next.js的useRouter:
import { useRouter } from 'next/router'; // 在组件内部 const router = useRouter(); // 解析URL参数,给默认值避免报错 const currentPage = Number(router.query.page) || 1; const currentLimit = Number(router.query.limit) || 10;
如果你用React Router的useSearchParams:
import { useSearchParams } from 'react-router-dom'; // 在组件内部 const [searchParams] = useSearchParams(); const currentPage = Number(searchParams.get('page')) || 1; const currentLimit = Number(searchParams.get('limit')) || 10;
这样就能动态获取当前所在的分页页码和每页条数了。
2. 用正确的缓存键执行Mutate
拿到分页参数后,生成和当前页面匹配的缓存键,然后根据场景选择两种更新方式:
方式一:手动更新缓存(无需重新请求)
如果确定用户修改后不会影响分页排序(比如只是改了出生日期),可以直接基于当前缓存的数据修改,避免额外的API请求:
// 生成当前页的缓存键 const currentCacheKey = `api/users?page=${currentPage}&limit=${currentLimit}`; // 在try块里替换原来的mutate代码 mutate(currentCacheKey, (currentCachedData) => { if (!currentCachedData) return currentCachedData; // 找到目标用户,替换为新数据 return { ...currentCachedData, users: currentCachedData.users.map(user => user.id === id ? { ...user, ...userData, birthdate: formattedBirthDate } : user ) }; }, { revalidate: false }); // 禁止自动重新请求,直接更新缓存
方式二:重新请求当前页数据(更稳妥)
如果用户的修改可能影响分页排序(比如改了用户名导致排序变化),最好让SWR重新请求当前页的数据,确保缓存完全同步:
const currentCacheKey = `api/users?page=${currentPage}&limit=${currentLimit}`; // 直接调用mutate,不传新数据,SWR会自动重新请求该URL的最新数据 mutate(currentCacheKey);
整合到你的原代码里
修改后的提交处理函数大概是这样:
import { useRouter } from 'next/router'; // 或者对应路由库的钩子 // 组件内部 const router = useRouter(); const currentPage = Number(router.query.page) || 1; const currentLimit = Number(router.query.limit) || 10; onSubmit={async (values, actions) => { const { birthdate, ...userData } = values; let formattedBirthDate = formatDate(birthdate); const updateUserUrl = `/api/users/update/${id}`; try { const res = await api.patch( updateUserUrl, { ...userData, birthdate: formattedBirthDate }, { headers: { "Auth-Token": authToken } } ); if (res && res.data) { // 生成当前页的缓存键 const currentCacheKey = `api/users?page=${currentPage}&limit=${currentLimit}`; // 选择上面的方式一或方式二更新缓存 mutate(currentCacheKey, (currentData) => { if (!currentData) return currentData; return { ...currentData, users: currentData.users.map(u => u.id === id ? { ...u, ...userData, birthdate: formattedBirthDate } : u ) }; }, { revalidate: false }); router.replace(`/admin?page=${currentPage}&limit=${currentLimit}`); toast.success("Updated successfully"); } } catch (error) { // 错误处理逻辑保持不变 if (error.response) { toast.error(error.response.data.message); console.log("Error response data: ", error.response.data); console.log("Error response status: ", error.response.status); console.log("Error response headers: ,", error.response.headers); } else { console.log("Error entity error: ", error.message); toast.error(error.message); } } }}
额外提示:批量更新所有分页缓存(可选)
如果你的用户数据可能出现在多个分页里,可以用SWR的模糊匹配功能(需SWR 1.0+)触发所有用户列表缓存的重新验证:
// 匹配所有以api/users开头的缓存键,重新请求数据 mutate(key => key.startsWith('api/users'), undefined, { revalidate: true });
不过这种方式会增加API调用量,只在必要时使用。
内容的提问来源于stack exchange,提问作者rainz
相关产品推荐
相关产品推荐

