TanStack Query ESLint 规则 no-unstable-deps 深度解析:为什么 Query Hook 返回值不能直接放进 React 依赖数组

发布时间:2026/9/6 18:51:09

TanStack Query ESLint 规则 no-unstable-deps 深度解析:为什么 Query Hook 返回值不能直接放进 React 依赖数组
TanStack Query ESLint 规则 no-unstable-deps 深度解析为什么 Query Hook 返回值不能直接放进 React 依赖数组【免费下载链接】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/queryno-unstable-deps是tanstack/eslint-plugin-query中专门针对「把 query hook 返回值整体塞进 React hook 依赖数组」这一反模式的静态检查规则。由于useQuery等 hook 返回的对象不具备引用稳定性直接将其写入useEffect、useMemo、useCallback的依赖数组会让依赖比较永远失效、副作用每次渲染都重新执行。读完本文你将掌握该规则的正确/错误写法、在 flat config 与 legacy config 下的启用方式以及规则在源码层面的判定逻辑如何识别 TanStack Query 导入、如何追踪自定义 hook 包装、useQueries的combine为何被豁免。规则背景哪些 hook 的返回值不受保护规则针对的是 no-unstable-deps.md 中列出的 7 个 hook它们返回的对象不具备引用稳定性not referentially stableuseQueryuseSuspenseQueryuseQueriesuseSuspenseQueriesuseInfiniteQueryuseSuspenseInfiniteQueryuseMutation正确做法是对返回值进行解构把解构出的属性如mutate、refetch、data放进依赖数组。依赖数组的语义是「只有当依赖项发生变化时才重新执行」而一个每次渲染都换身份的整对象会让这层保护形同虚设——规则正是为了在编译期拦截这类问题。规则细节错误与正确的代码示例以下示例完整继承自官方文档可直接复制到项目中使用。错误示例——把useMutation的完整返回值放入useCallback的依赖数组/* eslint tanstack/query/no-unstable-deps: warn */ import { useCallback } from react import { useMutation } from tanstack/react-query function Component() { const mutation useMutation({ mutationFn: (value: string) value }) const callback useCallback(() { mutation.mutate(hello) }, [mutation]) return null }命中规则时会收到如下报错模板来自规则源码中的messages.noUnstableDeps见 no-unstable-deps.rule.tsThe result of useMutation is not referentially stable, so dont pass it directly into the dependencies array of useCallback. Instead, destructure the return value of useMutation and pass the destructured values into the dependency array of useCallback.正确示例——解构出mutate再放入依赖数组/* eslint tanstack/query/no-unstable-deps: warn */ import { useCallback } from react import { useMutation } from tanstack/react-query function Component() { const { mutate } useMutation({ mutationFn: (value: string) value }) const callback useCallback(() { mutate(hello) }, [mutate]) return null }对 query 类 hook 同理例如const { refetch } useQuery({ queryKey, queryFn })后将refetch而非整个query对象放入依赖数组。规则属性与默认配置文档标注的属性✅ Recommended已纳入推荐配置不可自动修复Fixable 未勾选命中后需手动调整代码从源码可以进一步确认其严重级别规则meta声明type: problem、recommended: error且在插件的推荐配置中它被显式设为error。查看 index.ts 可以看到const recommendedRules { tanstack/query/exhaustive-deps: error, tanstack/query/no-rest-destructuring: warn, tanstack/query/stable-query-client: error, tanstack/query/no-unstable-deps: error, tanstack/query/infinite-query-property-order: error, tanstack/query/no-void-query-fn: error, tanstack/query/mutation-property-order: error, } as const也就是说只要启用插件的recommended/recommendedStrict或flat/recommended/flat/recommended-strict预设no-unstable-deps默认就以error级别生效无需单独配置。该规则schema: []不接受任何选项参数属于零配置规则。如何启用该规则Flat configESLint 9ESM推荐直接引用预设参考仓库内 eslint-plugin-demo 示例import pluginQuery from tanstack/eslint-plugin-query import tseslint from typescript-eslint export default [ ...tseslint.configs.recommended, ...pluginQuery.configs[flat/recommended], ]Legacy configeslintrc在plugins与extends中引用{ plugins: [tanstack/query], extends: [plugin:tanstack/query/recommended] }也可以在rules中单独调整级别例如tanstack/query/no-unstable-deps: warn即文档示例中内联注释所演示的写法。插件包为 tanstack/eslint-plugin-querypeer 依赖要求eslint ^8.57.0 || ^9.0.0 || ^10.0.0typescript为可选 peer 依赖^5.6.0 || ^6.0.0 || ^7.0.0配置时请以当前项目的 ESLint 版本为准。源码剖析规则如何判定「不稳定依赖」规则的完整实现在 no-unstable-deps.rule.ts其判定逻辑比文档描述的「不要整体放进依赖数组」要细致得多值得逐层拆解。监控对象两个 hook 名单规则顶部定义了两份名单L9-L18export const reactHookNames [useEffect, useCallback, useMemo] export const useQueryHookNames [ useQuery, useSuspenseQuery, useQueries, useSuspenseQueries, useInfiniteQuery, useSuspenseInfiniteQuery, ] const allHookNames [useMutation, ...useQueryHookNames]即规则只检查 React 三个常用副作用 hookuseEffect/useCallback/useMemo的依赖数组第二个参数必须是数组字面量只追踪上表 7 个 TanStack Query hook 的返回值变量。导入识别只对tanstack/*-query包生效规则通过detectTanstackQueryImports高阶工厂包裹detect-react-query-imports.ts。该工厂在扫描ImportDeclaration时只收集满足source.value.startsWith(tanstack/) source.value.endsWith(-query)的具名导入并暴露isTanstackQueryImport(node)供规则校验调用点。由此产生一条重要边界同名但来自其他模块的useQuery不会触发规则。测试用例中专门覆盖了这一点no-unstable-deps.test.ts// 来自 ./router / ./api 的同名 hook —— 属于 valid 用例不报错 import { useQuery } from ./router import { useMutation } from ./api返回值变量追踪与解构识别规则用trackedVariables: Recordstring, string变量名 → 所属 query hook记录每个 hook 调用结果「落到了哪些变量上」。collectVariableNames支持三种形态整体接收const mutation useMutation(...)—— 变量名记入追踪表之后该名字出现在依赖数组里即报错对象解构const { mutate } useMutation(...)—— 不会写入追踪表解构出的属性是稳定的因此[mutate]合法数组解构const [userQuery, ...restQueries] useQueries(...)—— 数组元素与 rest 元素RestElement都会被记入追踪表因此[userQuery]或[restQueries]均会报错。这与useQueries返回的每个元素本身也不稳定有关测试文件中的 invalid 用例覆盖了「解构出的单个元素」和「rest 元素」两种场景L343-L418。自定义 hook 包装也能被追踪很多项目不会直接调用useQuery而是封装一层useMyQuery。规则通过isCustomHookName正则/^use[A-Z0-9]/getReturnedQueryHook来识别这类包装函数只要函数体是「直接返回一个 query hook 调用」的单一return或箭头函数直接返回调用表达式该自定义 hook 就会被登记进trackedCustomHooks其返回值再传入依赖数组时同样报错。测试用例验证了两个细节L252-L341支持function useMyQuery() { return useQuery(...) }的函数声明形态与const useMyMutation () useMutation(...)的变量声明形态支持声明在使用之后的自定义 hook「result of later custom useQuery wrapper」用例。这正是规则把变量收集与依赖检查统一推迟到Program:exit阶段执行的原因L265-L280先遍历全部pendingVariableDeclarators建立追踪表再逐一检查pendingDependencyChecks从而消除声明顺序带来的假阴性。React hook 的别名与命名空间形式getReactHook同时识别三种调用形式L47-L65直接调用useCallback(fn, [deps])命名空间调用React.useCallback(fn, [deps])MemberExpression且对象为React导入别名import { useCallback as useAlias } from React中的useAlias(fn, [deps])别名在ImportDeclaration监听中写入hookAliasMap。测试套件正是按这 3 种导入风格 × 3 个 React hook 的矩阵展开执行全部用例的L421-L456。useQueries的combine豁免hasCombineProperty检查首个参数对象中是否存在combine属性L94-L109。当useQueries/useSuspenseQueries使用了combine时getDirectQueryHook返回undefined即不再追踪其返回值——因为combine的返回值是被框架 memo 化的稳定对象整体放入依赖数组是安全且常见的。对应 valid 用例const queries useQueries({ queries: [{ queryKey: [test], queryFn: () test }], combine: (results) ({ data: results[0]?.data }), }) const callback useCallback(() { queries.data }, [queries]) // 合法相反不带combine的useQueries整体传入依赖数组则是 invalid 用例。规则注册与消息结构规则经 rules.ts 注册进插件name常量no-unstable-deps即 ESLint 规则名完整规则名为tanstack/query/no-unstable-deps。唯一的消息 id 是noUnstableDeps数据槽位为queryHook命中的 query hook 名与reactHook命中的 React hook 名报错位置精确指向依赖数组中那个不稳定标识符本身便于编辑器跳转定位。实战清单什么样的依赖写法会被拦结合源码与测试可以归纳出一份速查表写法是否报错[mutation]mutation为useMutation返回值报错[query]query为useQuery等返回值报错[userQuery]useQueries数组解构出的单个元素报错[restQueries]useQueries解构的 rest 元素报错[result]result来自自定义包装 hook直接 return query hook报错[queries]useQueries({ ..., combine })的结果合法[mutate]、[refetch]、[data]等解构属性合法同名 hook 但来自非tanstack/*-query模块合法不检查useEffect(fn)不传第二参数 / 非数组第二参数不检查几条实用建议依赖数组里永远只放解构后的原始值或稳定引用这同时满足no-unstable-deps与 React 官方的依赖原则也和插件姊妹规则tanstack/query/exhaustive-deps的检查方向互补需要把多个 query 的data汇总给下游 hook 时优先考虑useQueries的combine它既能产出稳定对象又能绕开本规则的拦截由于该规则不可自动修复建议在代码评审中把「依赖数组里出现 hook 整体返回值」作为必查项或直接依赖recommended预设的error级别在 CI 中拦截。参考文件规则文档docs/eslint/no-unstable-deps.md规则实现packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts规则测试含 valid/invalid 全矩阵packages/eslint-plugin-query/src/tests/no-unstable-deps.test.ts导入检测工具packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts推荐预设与规则注册packages/eslint-plugin-query/src/index.ts、packages/eslint-plugin-query/src/rules.tsFlat config 使用示例examples/react/eslint-plugin-demo/eslint.config.js【免费下载链接】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),仅供参考

相关新闻

container:如何提交高质量 Bug 报告——从环境信息采集到日志抓取完整指南

container:如何提交高质量 Bug 报告——从环境信息采集到日志抓取完整指南

2026/9/6 18:51:09

container:如何提交高质量 Bug 报告——从环境信息采集到日志抓取完整指南 【免费下载链接】container A tool for creating and running Linux containers using lightweight virtual machines on a Mac. It is written in Swift, and optimized for Apple silicon…

FPGA交通灯控制器设计:从状态机到上板调试全解析

FPGA交通灯控制器设计:从状态机到上板调试全解析

2026/9/6 18:51:09

简介:基于FPGA的交通灯控制器设计PDF,面向电子工程、嵌入式及FPGA初学者,讲解如何用VHDL在QuartusⅡ中实现四方向红黄绿交通灯控制,包含分频器、译码器、位选器等模块设计,可解决交通信号时序控制与紧急状态处理问题。…

FreeTube护眼模式3步上手:夜间看视频如何过滤蓝光

FreeTube护眼模式3步上手:夜间看视频如何过滤蓝光

2026/9/6 18:51:09

FreeTube护眼模式3步上手:夜间看视频如何过滤蓝光 【免费下载链接】FreeTube An Open Source YouTube app for privacy 项目地址: https://gitcode.com/GitHub_Trending/fr/FreeTube 睡前1点,你还在笔记本上追剧。屏幕泛着刺眼的白光,…

基于STM32的智能家居多功能护眼台灯设计与实现

基于STM32的智能家居多功能护眼台灯设计与实现

2026/9/6 19:51:13

简介:基于STM32的智能家居护眼台灯设计与实现论文模版,面向具备单片机基础的电子信息类专业学生及嵌入式开发爱好者,可解决智能照明系统毕业设计选题、方案设计与论文撰写的参考需求。内容围绕自动调光、坐姿检测、人体检测、手势控制及手机远…

辽宁学位日语样题深度解析:艺术体育二外类考生备考策略

辽宁学位日语样题深度解析:艺术体育二外类考生备考策略

2026/9/6 19:51:13

简介:辽宁省成人本科毕业生学士学位考试日语(艺术、体育、二外类)样题文档,面向备考该科目、需要熟悉题型与难度的考生。内容涵盖日语词汇读音选择、汉字书写辨析以及语境选词填空等核心考查模块,并附有具体例题与选项…

气固两相流动数值模拟:模型选型与工程实践精要

气固两相流动数值模拟:模型选型与工程实践精要

2026/9/6 19:51:13

简介:《气固两相流动与数值模拟》PDF文档面向化工、能源、环境及航空航天等领域的研究人员、工程师与Fluent初学者,系统讲解气固两相流的关键建模方法。内容覆盖离散相模型(DPM)、Euler-Euler与Euler-Lagrange连续介质模型&#x…

ETH_03测量分析实战:从需求拆解到数据处理的完整链路

ETH_03测量分析实战:从需求拆解到数据处理的完整链路

2026/9/6 19:51:13

简介:面向车载以太网测试与诊断工程师,这份CANoe/CANalyzer操作指南聚焦以太网测量分析技术在车辆电子系统测试与诊断中的应用,内容从测量分析的基本概念切入,逐步覆盖数据捕获、过滤器配置、日志记录、离线分析、交互发送以及诊断…

LEED认证全解析:从评分表到能耗模拟的绿建落地指南

LEED认证全解析:从评分表到能耗模拟的绿建落地指南

2026/9/6 19:51:13

简介:这是一份LEED(能源与环境设计先锋)绿色建筑认证体系的中文版借鉴资料,适合建筑设计师、工程管理人员及施工单位参考,用于理解在中国落地LEED标准时的具体要求和实施办法。文档基于某工业厂房总包招标文件整理&…

CMG STARS油藏数值模拟入门:蒸汽吞吐建模与收敛问题排查

CMG STARS油藏数值模拟入门:蒸汽吞吐建模与收敛问题排查

2026/9/6 19:41:13

简介:这份PPT是CMG数模软件STARS模块的入门教程,面向油气藏数值模拟初学者及相关工程技术人员,内容源自中国石油大学(北京)的培训课程。STARS模块是热采、泡沫及复杂流体模拟的三维数值模拟器,教程围绕模拟…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/6 1:19:56

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/6 1:19:56

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/6 1:19:56

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/6 1:19:56

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/6 1:19:56

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/6 1:19:56

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

远程协作的工作台整理

远程协作的工作台整理

2026/9/3 6:56:24

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/4 7:42:10

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/5 23:14:13

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…