mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[lint] Use settings for additional hooks in exhaustive deps (#34637)
Like in the diff below, we can read from the shared configuration to check exhaustive deps. I allow the classic additionalHooks configuration to override it so that this change is backwards compatible. -- --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34637). * __->__ #34637 * #34497
This commit is contained in:
@@ -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-hooks': {
|
||||
additionalEffectHooks: 'useCustomEffect',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test settings-based additionalHooks - should work with dependencies
|
||||
code: normalizeIndent`
|
||||
function MyComponent(props) {
|
||||
useCustomEffect(() => {
|
||||
console.log(props.foo);
|
||||
}, [props.foo]);
|
||||
}
|
||||
`,
|
||||
settings: {
|
||||
'react-hooks': {
|
||||
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-hooks': {
|
||||
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-hooks': {
|
||||
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-hooks': {
|
||||
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() {
|
||||
|
||||
@@ -21,6 +21,8 @@ import type {
|
||||
VariableDeclarator,
|
||||
} from 'estree';
|
||||
|
||||
import { getAdditionalEffectHooksFromSettings } from '../shared/Utils';
|
||||
|
||||
type DeclaredDependency = {
|
||||
key: string;
|
||||
node: Node;
|
||||
@@ -69,19 +71,22 @@ 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;
|
||||
: getAdditionalEffectHooksFromSettings(settings);
|
||||
|
||||
const enableDangerousAutofixThisMayCauseInfiniteLoops: boolean =
|
||||
(rawOptions &&
|
||||
@@ -93,7 +98,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 +1357,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\``,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user