ARTICLE DETAIL

资讯详情

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

React Query 的 useIsMutating 全面解析:精确统计应用中正在执行的 mutation 数量

React Query 的 useIsMutating 全面解析:精确统计应用中正在执行的 mutation 数量 React Query 的 useIsMutating 全面解析精确统计应用中正在执行的 mutation 数量【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/queryuseIsMutating 是 TanStack Query React 适配层提供的可选订阅式 Hook用于返回应用内当前正在执行pending的 mutation 数量是构建全应用范围“保存中/提交中”全局加载指示器的标准工具。本篇以 docs/framework/react/reference/functions/useIsMutating.md 为主体结合仓库内 React Query 与 query-core 的源码实现完整讲解其签名、MutationFilters 过滤规则、参数语义、返回值的更新时机以及底层订阅原理使读者既能直接上手也能理解其内部机制。useIsMutating 是什么解决什么问题在包含多条 mutation 的应用里往往需要一种“全局视角”的信号无论某个提交动作发生在哪个组件只要背后还有 mutation 在执行顶栏、遮罩层或全局进度条就应显示 loading 状态。useIsMutating就是为此设计的“可选optionalHook”官方注释称它“returns the number of mutations that your application is fetching”常用于全应用范围的加载指示器app-wide loading indicators。它与useMutation返回的单个isPending不同后者只反映当前组件内这一条 mutation 的执行状态而useIsMutating会遍历整个MutationCache统计所有“正在执行”的 mutation并支持通过MutationFilters把它们精确缩小到某一部分例如只统计mutationKey以posts开头的提交。API 签名与参数原始文档给出如下类型签名function useIsMutating(filters?, queryClient?): number两个入参均为可选说明如下参数类型说明filtersMutationFiltersunknown, Error, unknown, unknown用于缩小匹配范围的 Mutation 过滤器见下文「MutationFilters 详解」queryClientQueryClient传入自定义QueryClient不传时使用最近上下文Provider提供的实例queryClient的语义与useQuery、useMutation一致若应用通过QueryClientProvider注入了默认 client通常无需传第二个参数。它最终由useQueryClient(queryClient)解析——若显式传入则直接使用否则回退到 React Context 中最近的 provider对应实现见 useQueryClient 的取值逻辑。返回值类型为number即“当前正在执行的 mutation 的数量”。基础用法全应用与按 key 过滤的加载指示器沿用文档自带示例按 mutationKey 前缀统计“正在保存的 posts 类提交”import { useIsMutating } from tanstack/react-query function PostsMutatingIndicator() { // How many mutations matching the posts prefix are in progress? const isMutatingPosts useIsMutating({ mutationKey: [posts] }) return isMutatingPosts ? spanSaving posts.../span : null }未传任何过滤条件时useIsMutating()统计应用内所有处于 pending 的 mutation典型场景是全局顶部进度条或按钮禁用逻辑传入{ mutationKey: [posts] }后只统计该 key 前缀命中的 mutation。这里mutationKey采用**前缀匹配partial match**语义见下文matchMutation的实现。与查询侧对照若想统计“后台正在拉取的查询数量”可参考兄弟 Hook useIsFetching其用法几乎对称只是过滤器类型为QueryFilters。MutationFilters 详解精确控制统计范围过滤条件即MutationFilters类型其字段定义位于 query-core 的 utils.tsexport interface MutationFilters TData unknown, TError DefaultError, TVariables unknown, TOnMutateResult unknown, { /** Match mutation key exactly */ exact?: boolean /** Include mutations matching this predicate function */ predicate?: (mutation: MutationTData, TError, TVariables, TOnMutateResult) boolean /** Include mutations matching this mutation key */ mutationKey?: TuplePrefixesMutationKey /** Filter by mutation status */ status?: MutationStatus }各字段的匹配语义由 matchMutation 落实可作为判断“某条 mutation 是否计入”的依据mutationKey筛选拥有给定 mutation key 的 mutation。注意被匹配的 mutation本身必须显式设置了mutationKey即mutation.options.mutationKey存在否则直接判定不匹配。exact布尔值决定 key 匹配是否要求“完全相等”。为false默认时走前缀/部分匹配partialMatchKey为true时则对 key 做哈希hashKey后精确比对matchMutation中hashKey(mutation.options.mutationKey) ! hashKey(mutationKey)即不匹配。这与查询侧QueryFilters的exact行为相对应。status按 mutation 的status过滤取值如pending、success、error、idle等mutation.state.status。只有当 mutation 当前状态与给定值一致时才会被计入。predicate自定义判定函数接收该mutation实例返回布尔值。这是最灵活的过滤手段例如可以结合mutation.state中的自定义条件做复杂筛选。过滤执行顺序与真实数据源useIsMutating内部依赖MutationCache.findAll其实现为 mutationCache.ts 的 findAllfindAll(filters: MutationFilters {}): ArrayMutation { return this.getAll().filter((mutation) matchMutation(filters, mutation)) }即从MutationCache中的全部 mutation 里逐条执行matchMutation过滤因此返回值的语义严格等价于“mutationCache.findAll(filters).length”。返回值语义统计的是哪些 mutation文档明确返回值是“currently fetching”的 mutation 数量。需要厘清的是——它不会把已成功、已失败或尚未执行的 mutation 计入。关键证据在于useIsMutating的源码实现react-query/src/useMutationState.ts#L35-L44export function useIsMutating( filters?: MutationFilters, queryClient?: QueryClient, ): number { const client useQueryClient(queryClient) return useMutationState( { filters: { ...filters, status: pending } }, client, ).length }它本质是useMutationState的一个特化调用在用户传入的filters之上强制注入status: pending再对返回的 mutation 数组求length。换句话说无论调用方是否显式指定status统计范围都会被收敛到“处于 pending正在执行状态”的 mutation。这与命令式 API QueryClient.isMutating 完全同构isMutating TMutationFilters extends MutationFiltersany, any MutationFilters, (filters?: TMutationFilters): number { return this.#mutationCache.findAll({ ...filters, status: pending }).length }二者采用同一判定口径因此你在任何地方Hook 内或回调中得到的“正在执行的 mutation 数”都是一致的。底层原理useMutationState 与响应式订阅useIsMutating之所以能随 mutation 开始/结束而实时返回新数字关键在于其底层useMutationState的实现useMutationState.ts#L157-L194它完成三件事获取缓存源useQueryClient(queryClient).getMutationCache()即从上下文中取 client 并拿到全局MutationCache。同步计算快照首次渲染时通过getResult(mutationCache, options)执行findAll并映射出结果数组getResult还支持select转换函数默认取mutation.state。订阅变化借助React.useSyncExternalStore订阅mutationCache。useIsMutating关心的正是订阅回调触发时findAll之后length的新值。订阅回调内部值得注意的两个优化点replaceEqualDeep来自tanstack/query-core对新旧结果做结构化深比较只有结果真正变化时才更新内部引用并触发重渲染避免无关的缓存事件造成无谓渲染notifyManager.schedule把对外通知调度到下一帧批量执行配合 mutation cache 内部的notifyManager.batchmutationCache.ts#L223-L229保证一次批量状态变更例如多条 mutation 同时完成只触发一次 UI 刷新。useIsMutating正是将上述订阅能力的返回值length暴露给组件每当有 mutation 进入pending、完成或失败离开 pending缓存广播通知findAll结果随之变化计数即被刷新。整个过程无网络请求参与纯属对内存中 mutation 状态机的心智同步。典型场景实践全局提交进度条在根布局中直接useIsMutating()非 0 时显示“有更改正在提交”的全局指示无需逐条 mutation 单独接线。局部表单禁用如示例所示useIsMutating({ mutationKey: [posts] })仅当 posts 相关的写入仍在进行时才在保存按钮上叠加禁用/文案。组合mutationKey前缀设计由于默认是部分匹配合理的 key 分层如[posts]与[posts, postId]可让上层统计自然覆盖下层全部子提交这是官方示例使用前缀过滤的工程价值所在。复杂条件筛选若前缀匹配不够可在filters中使用predicate: (m) ...自行判断是否计入过滤精度由你完全掌控。注意事项与对比总结useIsMutating只关心 mutation 执行状态不关心 mutation 的目标数据与“查询是否在拉取”对应的工具是useIsFetching二者常常配合使用一个覆盖读、一个覆盖写来拼装完整的全局 loading 信号。计数结果与useMutation返回的mutation.isPending口径一致v5 中以pending状态表达“执行中”但它以 MutationCache 为全局视角聚合多条 mutation不要试图用它获得某条 mutation 的具体数据——若需要按 key 读取某次提交的状态或结果应使用底层特化前的完整 Hook useMutationState它支持select返回任意派生数据例如全部 pending mutation 的variables、最近一次成功提交的data等。返回值是标准 React 响应式数字直接可用于条件渲染在并发 mutation 频繁增删的页面中得益于深比较与批处理通知它不会因无关缓存事件引起抖动。文档与实现均表明该 Hook 为“optional”能力你的应用完全可以不关心全局 mutation 计数仅在确实需要全应用写入指示时引入。参考与延伸阅读官方参考文档原文useIsMutatingReactHook 类型签名与特化实现useMutationState.ts、useIsFetching.tsMutation 过滤器类型与匹配算法utils.ts 中 MutationFilters / matchMutation缓存遍历与通知MutationCache.findAll / notify命令式等价 APIQueryClient.isMutating其他框架对应文档useIsMutatingPreact、useIsMutatingLit、useIsMutatingSvelte、useIsMutatingVue、useIsMutatingSolid【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表