ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SWR 数据变更指南:使用 mutate 实现本地更新、远程请求与重新验证(Nextra swr-site 示例)

SWR 数据变更指南:使用 mutate 实现本地更新、远程请求与重新验证(Nextra swr-site 示例) SWR 数据变更指南使用 mutate 实现本地更新、远程请求与重新验证Nextra swr-site 示例【免费下载链接】nextraSimple, powerful and flexible site generation framework with everything you love from Next.js.项目地址: https://gitcode.com/GitHub_Trending/ne/nextra本指南以 swr-site 示例仓库中的 Mutation 文档 为主体系统讲解 SWR 中mutate的四种核心用法全局广播重新验证、本地乐观更新 POST 请求、基于当前缓存值的异步更新、以及 useSWR 返回的预绑定 mutate。读完本文你将掌握如何在 React 应用中即时更新缓存、减少等待远程响应的卡顿并避免常见的缓存不一致问题。为什么需要 mutateSWR 缓存与手动变更SWRstale-while-revalidate默认会在组件挂载、窗口聚焦、网络重连等时机自动重新验证数据详见 自动重新验证文档。但自动重新验证无法覆盖所有场景——例如用户点击退出登录后需要立即让全站所有使用同一 key 的 SWR hook 失效并重新拉取此时就需要手动触发变更。SWR 将缓存写入能力封装为mutateAPI它允许你向同一 key 作用域内的所有 SWR hook 广播重新验证消息先更新本地缓存乐观更新再发起远程请求让界面响应更快基于当前缓存值计算并写入新的数据捕获更新过程中的错误并进行处理。需要注意的是SWR 文档明确警告大多数情况下不应直接向缓存写入数据见 Cache 文档 中的警告手动变更 key 请一律走 SWR 提供的mutate等公开 API否则可能引发不可预期的行为。重新验证Revalidate全局广播同一 key你可以从useSWRConfig()hook 中获取mutate函数并通过调用mutate(key)向使用相同 key的其他 SWR hook 全局广播一条重新验证消息。下面的例子展示了当用户点击 Logout 按钮时如何自动重新拉取登录信息例如Profile组件中的数据import useSWR, { useSWRConfig } from swr function App() { const { mutate } useSWRConfig() return ( div Profile / button onClick{() { // set the cookie as expired document.cookie token; expiresThu, 01 Jan 1970 00:00:00 UTC; path/; // tell all SWRs with this key to revalidate mutate(/api/user) }} Logout /button /div ) }这里的关键在于 key 的作用域mutate只广播到同一 cache provider 作用域下的 SWR hook。如果没有显式配置 cache provider则广播到所有 SWR hook。关于 cache provider 的作用域边界可参考 Cache Provider 文档It broadcasts to SWR hooks under the same cache provider scope. If no cache provider exists, it will broadcast to all SWR hooks.当存在自定义 cache provider 时还有一个重要限制如果使用了 cache provider全局mutate将不会对该SWRConfig边界内的 SWR hook 生效此时需要改用useSWRConfig获取当前作用域内的mutate。这是因为useSWRConfig返回的mutate已经绑定到当前缓存提供者而全局导出的mutate只面向默认缓存。变更与 POST 请求乐观更新三步法在许多场景下对数据应用**本地变更local mutation**是让操作感觉更快的好方法——无需等待远程数据源返回。mutate允许你以编程方式更新本地数据同时触发重新验证最终用最新数据替换本地数据。经典模式是本地更新 → 发送请求 → 重新验证import useSWR, { useSWRConfig } from swr function Profile() { const { mutate } useSWRConfig() const { data } useSWR(/api/user, fetcher) return ( div h1My name is {data.name}./h1 button onClick{async () { const newName data.name.toUpperCase() // update the local data immediately, but disable the revalidation mutate(/api/user, { ...data, name: newName }, false) // send a request to the API to update the source await requestUpdateUsername(newName) // trigger a revalidation (refetch) to make sure our local data is correct mutate(/api/user) }} Uppercase my name! /button /div ) }点击按钮后发生的事先在本地把客户端数据改为全大写名字第三参false表示不触发重新验证再发送 POST 请求修改远程数据最后再调用一次mutate(/api/user)拉取最新数据确认本地数据正确。然而许多 POST API 会直接返回更新后的数据此时无需再重新验证。下面展示 local mutate - request - update本地变更 - 请求 - 更新的紧凑写法mutate(/api/user, newUser, false) // use false to mutate without revalidation mutate(/api/user, updateUser(newUser), false) // updateUser is a Promise of the request, // which returns the updated document第二个参数既可以是普通数据也可以是一个返回 Promise 的函数——当它是 Promise 时SWR 会等待其 resolve 后用返回值更新缓存。mutate的完整函数签名与返回值可对照 API Options 文档const { data, error, isValidating, mutate } useSWR(key, fetcher, options) // mutate(data?, shouldRevalidate?): function to mutate the cached data其中第二参shouldRevalidate控制本次变更后是否重新验证默认true传入false即可实现纯本地更新。基于当前数据变更Mutate Based on Current Data有时你只想基于当前缓存值更新数据的一部分。此时可以给mutate传入一个异步函数该函数会接收当前的缓存值如果存在并返回更新后的文档mutate(/api/todos, async todos { // lets update the todo with ID 1 to be completed, // this API returns the updated data const updatedTodo await fetch(/api/todos/1, { method: PATCH, body: JSON.stringify({ completed: true }) }) // filter the list, and return it with the updated item const filteredTodos todos.filter(todo todo.id ! 1) return [...filteredTodos, updatedTodo] })这段代码的关键点回调函数收到当前缓存中的todos数组发起 PATCH 请求更新远程的 todo1拿到服务端返回的updatedTodo从本地数组中过滤掉旧项再拼入更新后的项返回值即新的缓存内容。由于回调是异步的你可以在其中做任意复杂操作多个请求、条件分支等只要最终返回更新后的文档即可。这种方式既保持了乐观更新的即时反馈又确保了最终写入缓存的数据与远程一致。mutate 的返回值与错误处理大多数情况下你需要用某些数据更新缓存这些数据来自你传给mutate的 Promise 或异步函数 resolve 之后的结果。函数执行期间如果抛出错误该错误会被原样抛出以便你在调用处处理try { const user await mutate(/api/user, updateUser(newUser)) } catch (error) { // Handle an error while updating the user here }因此mutate天然支持async/await与try/catch成功时拿到更新后的文档失败时捕获错误。这也意味着你可以把mutate直接作为 Promise 链的一环与其它异步逻辑组合而不用担心错误被静默吞掉。预绑定 MutateBound MutateuseSWR返回的 SWR 对象中也包含一个mutate()函数它预绑定到该 hook 的 key 上。它与全局mutate功能等价但不需要传入 key 参数import useSWR from swr function Profile() { const { data, mutate } useSWR(/api/user, fetcher) return ( div h1My name is {data.name}./h1 button onClick{async () { const newName data.name.toUpperCase() // send a request to the API to update the data await requestUpdateUsername(newName) // update the local data immediately and revalidate (refetch) // NOTE: key is not required when using useSWRs mutate as its pre-bound mutate({ ...data, name: newName }) }} Uppercase my name! /button /div ) }预绑定mutate的使用场景组件内只需要更新自己负责的那一个 key时直接调用mutate(data?, shouldRevalidate?)即可签名与 API Options 文档 中列出的返回项一致。由于它无需手动维护 key 字符串在 key 由函数或复杂结构生成时见 Conditional Data Fetching可以避免拼错 key 导致缓存更新不到位的隐患。全局 mutate 与 useSWRConfig 的关系本指南反复出现的useSWRConfig()是访问全局配置与变更能力的标准入口。从 Global Configuration 文档 可以看到它同时返回refreshInterval等全局配置以及mutate和cacheimport { useSWRConfig } from swr function Component() { const { refreshInterval, mutate, cache, ...restConfig } useSWRConfig() // ... }嵌套的配置会被扩展如果没有使用任何SWRConfig则返回默认配置。理解这一点有助于判断mutate的作用域——正如本文第一部分所述在自定义 cache provider 边界内请始终通过useSWRConfig获取 mutate而不是依赖全局导出的版本。进阶延伸用 cache provider 实现批量变更理解了mutate基于 key 广播的机制后还可以借助 cache provider API 构建更强的辅助函数。例如在 Cache 文档 中官方展示了一个正则匹配批量变更的useMatchMutatehook它遍历当前 cache 的所有 key对匹配正则的 key 逐一调用mutate再通过Promise.all聚合结果function useMatchMutate() { const { cache, mutate } useSWRConfig() return (matcher, ...args) { if (!(cache instanceof Map)) { throw new Error( matchMutate requires the cache provider to be a Map instance ) } const keys [] for (const key of cache.keys()) { if (matcher.test(key)) { keys.push(key) } } const mutations keys.map(key mutate(key, ...args)) return Promise.all(mutations) } }使用方式function Button() { const matchMutate useMatchMutate() return ( button onClick{() matchMutate(/^\/api\//)} Revalidate all keys start with /api/ /button ) }这一示例印证了mutate的底层机制它是围绕 cache 的 key 进行读写与广播的 API掌握 key 与 cache provider 作用域就能组合出符合业务需要的批量变更、按前缀失效等能力。小结mutate是 SWR 数据变更的核心 API四种用法对应四类常见需求用法适用场景关键点mutate(key)全局广播重新验证如退出登录后刷新全站用户信息同一 cache provider 作用域内生效mutate(key, data, false) 请求 mutate(key)乐观更新 远程请求 最终校正第三参false关闭本次重新验证mutate(key, async current next)基于当前缓存值做增量更新如修改列表中的一项回调接收当前缓存值返回值即新缓存useSWR返回的预绑定mutate只更新当前 hook 自己的 key无需传 key签名mutate(data?, shouldRevalidate?)本文所有示例均来自 Mutation 文档相关配套内容可继续查阅 API Options、Global Configuration 与 Cache 章节。在实战中建议遵循优先用 mutate 公开 API、不要直接写缓存的原则再结合场景选择上述模式即可在获得即时反馈的同时保证数据一致性。【免费下载链接】nextraSimple, powerful and flexible site generation framework with everything you love from Next.js.项目地址: https://gitcode.com/GitHub_Trending/ne/nextra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表