diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 812c2010a0..4df191fc89 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -1485,6 +1485,70 @@ const tests = { } `, }, + { + // Test settings-based additionalHooks - should work with settings + code: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }); + } + `, + settings: { + 'react-eslint': { + additionalEffectHooks: 'useCustomEffect', + }, + }, + }, + { + // Test settings-based additionalHooks - should work with dependencies + code: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }, [props.foo]); + } + `, + settings: { + 'react-eslint': { + additionalEffectHooks: 'useCustomEffect', + }, + }, + }, + { + // Test that rule-level additionalHooks takes precedence over settings + code: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }, []); + } + `, + options: [{additionalHooks: 'useAnotherEffect'}], + settings: { + 'react-eslint': { + additionalEffectHooks: 'useCustomEffect', + }, + }, + }, + { + // Test settings with multiple hooks pattern + code: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }, [props.foo]); + useAnotherEffect(() => { + console.log(props.bar); + }, [props.bar]); + } + `, + settings: { + 'react-eslint': { + additionalEffectHooks: '(useCustomEffect|useAnotherEffect)', + }, + }, + }, ], invalid: [ { @@ -3714,6 +3778,40 @@ const tests = { }, ], }, + { + // Test settings-based additionalHooks - should detect missing dependency + code: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }, []); + } + `, + settings: { + 'react-eslint': { + additionalEffectHooks: 'useCustomEffect', + }, + }, + errors: [ + { + message: + "React Hook useCustomEffect has a missing dependency: 'props.foo'. " + + 'Either include it or remove the dependency array.', + suggestions: [ + { + desc: 'Update the dependencies array to be: [props.foo]', + output: normalizeIndent` + function MyComponent(props) { + useCustomEffect(() => { + console.log(props.foo); + }, [props.foo]); + } + `, + }, + ], + }, + ], + }, { code: normalizeIndent` function MyComponent() { diff --git a/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts b/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts index d59a1ff792..7565779d64 100644 --- a/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts +++ b/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts @@ -69,19 +69,25 @@ const rule = { }, requireExplicitEffectDeps: { type: 'boolean', - } + }, }, }, ], }, create(context: Rule.RuleContext) { const rawOptions = context.options && context.options[0]; + const settings = context.settings || {}; + // Parse the `additionalHooks` regex. + // Use rule-level additionalHooks if provided, otherwise fall back to settings const additionalHooks = rawOptions && rawOptions.additionalHooks ? new RegExp(rawOptions.additionalHooks) - : undefined; + : settings['react-eslint'] && + settings['react-eslint'].additionalEffectHooks + ? new RegExp(settings['react-eslint'].additionalEffectHooks) + : undefined; const enableDangerousAutofixThisMayCauseInfiniteLoops: boolean = (rawOptions && @@ -93,7 +99,8 @@ const rule = { ? rawOptions.experimental_autoDependenciesHooks : []; - const requireExplicitEffectDeps: boolean = rawOptions && rawOptions.requireExplicitEffectDeps || false; + const requireExplicitEffectDeps: boolean = + (rawOptions && rawOptions.requireExplicitEffectDeps) || false; const options = { additionalHooks, @@ -1351,7 +1358,7 @@ const rule = { node: reactiveHook, message: `React Hook ${reactiveHookName} always requires dependencies. ` + - `Please add a dependency array or an explicit \`undefined\`` + `Please add a dependency array or an explicit \`undefined\``, }); }