diff --git a/.changeset/fix-no-unstable-deps-prototype-lookup.md b/.changeset/fix-no-unstable-deps-prototype-lookup.md new file mode 100644 index 00000000000..2ed2fbd308f --- /dev/null +++ b/.changeset/fix-no-unstable-deps-prototype-lookup.md @@ -0,0 +1,5 @@ +--- +'@tanstack/eslint-plugin-query': patch +--- + +Fix false positive in `no-unstable-deps` when a variable is assigned from a call whose name matches an `Object.prototype` method (e.g. `toString`, `valueOf`, `constructor`). diff --git a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts index fca18c41cd2..141cf450d7b 100644 --- a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts @@ -405,3 +405,29 @@ reactHookNames.forEach((reactHookName) => { }, ) }) + +const protoMethodNames = [ + 'toString', + 'valueOf', + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', +] as const + +ruleTester.run('no-unstable-deps', rule, { + valid: protoMethodNames.map((method) => ({ + name: `should not flag variable from "${method}()" call as unstable dep`, + code: ` + import { useCallback } from "React"; + + function Component() { + const result = ${method}(); + const cb = useCallback(() => { result }, [result]); + return null; + } + `, + })), + invalid: [], +}) diff --git a/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts b/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts index 934773faa0f..edb2732ee28 100644 --- a/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts +++ b/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts @@ -139,7 +139,10 @@ export const rule = createRule({ } if (callExpression.callee.type === AST_NODE_TYPES.Identifier) { - return trackedCustomHooks[callExpression.callee.name] + const calleeName = callExpression.callee.name + return Object.hasOwn(trackedCustomHooks, calleeName) + ? trackedCustomHooks[calleeName] + : undefined } return undefined