eslint-plugin-react-hooks 6.1.0-canary-6de32a5a-20250822 → 6.1.0-canary-33a1095d-20250827
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -17993,14 +17993,20 @@ var ErrorCategory;
|
|
|
17993
17993
|
ErrorCategory["Fire"] = "Fire";
|
|
17994
17994
|
ErrorCategory["FBT"] = "FBT";
|
|
17995
17995
|
})(ErrorCategory || (ErrorCategory = {}));
|
|
17996
|
+
const RULE_NAME_PATTERN = /^[a-z]+(-[a-z]+)*$/;
|
|
17996
17997
|
function getRuleForCategory(category) {
|
|
17998
|
+
const rule = getRuleForCategoryImpl(category);
|
|
17999
|
+
invariant(RULE_NAME_PATTERN.test(rule.name), `Invalid rule name, got '${rule.name}' but rules must match ${RULE_NAME_PATTERN.toString()}`);
|
|
18000
|
+
return rule;
|
|
18001
|
+
}
|
|
18002
|
+
function getRuleForCategoryImpl(category) {
|
|
17997
18003
|
switch (category) {
|
|
17998
18004
|
case ErrorCategory.AutomaticEffectDependencies: {
|
|
17999
18005
|
return {
|
|
18000
18006
|
category,
|
|
18001
18007
|
name: 'automatic-effect-dependencies',
|
|
18002
18008
|
description: 'Verifies that automatic effect dependencies are compiled if opted-in',
|
|
18003
|
-
recommended:
|
|
18009
|
+
recommended: false,
|
|
18004
18010
|
};
|
|
18005
18011
|
}
|
|
18006
18012
|
case ErrorCategory.CapitalizedCalls: {
|
|
@@ -18015,7 +18021,7 @@ function getRuleForCategory(category) {
|
|
|
18015
18021
|
return {
|
|
18016
18022
|
category,
|
|
18017
18023
|
name: 'config',
|
|
18018
|
-
description: 'Validates the configuration',
|
|
18024
|
+
description: 'Validates the compiler configuration options',
|
|
18019
18025
|
recommended: true,
|
|
18020
18026
|
};
|
|
18021
18027
|
}
|
|
@@ -18039,7 +18045,7 @@ function getRuleForCategory(category) {
|
|
|
18039
18045
|
return {
|
|
18040
18046
|
category,
|
|
18041
18047
|
name: 'set-state-in-effect',
|
|
18042
|
-
description: 'Validates against calling setState synchronously in an effect',
|
|
18048
|
+
description: 'Validates against calling setState synchronously in an effect, which can lead to re-renders that degrade performance',
|
|
18043
18049
|
recommended: true,
|
|
18044
18050
|
};
|
|
18045
18051
|
}
|
|
@@ -18047,7 +18053,7 @@ function getRuleForCategory(category) {
|
|
|
18047
18053
|
return {
|
|
18048
18054
|
category,
|
|
18049
18055
|
name: 'error-boundaries',
|
|
18050
|
-
description: 'Validates usage of error boundaries instead of try/catch for errors in
|
|
18056
|
+
description: 'Validates usage of error boundaries instead of try/catch for errors in child components',
|
|
18051
18057
|
recommended: true,
|
|
18052
18058
|
};
|
|
18053
18059
|
}
|
|
@@ -18071,7 +18077,7 @@ function getRuleForCategory(category) {
|
|
|
18071
18077
|
return {
|
|
18072
18078
|
category,
|
|
18073
18079
|
name: 'gating',
|
|
18074
|
-
description: 'Validates configuration of gating mode',
|
|
18080
|
+
description: 'Validates configuration of [gating mode](https://react.dev/reference/react-compiler/gating)',
|
|
18075
18081
|
recommended: true,
|
|
18076
18082
|
};
|
|
18077
18083
|
}
|
|
@@ -18079,7 +18085,8 @@ function getRuleForCategory(category) {
|
|
|
18079
18085
|
return {
|
|
18080
18086
|
category,
|
|
18081
18087
|
name: 'globals',
|
|
18082
|
-
description: 'Validates against assignment/mutation of globals during render'
|
|
18088
|
+
description: 'Validates against assignment/mutation of globals during render, part of ensuring that ' +
|
|
18089
|
+
'[side effects must render outside of render](https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
|
|
18083
18090
|
recommended: true,
|
|
18084
18091
|
};
|
|
18085
18092
|
}
|
|
@@ -18095,7 +18102,7 @@ function getRuleForCategory(category) {
|
|
|
18095
18102
|
return {
|
|
18096
18103
|
category,
|
|
18097
18104
|
name: 'immutability',
|
|
18098
|
-
description: 'Validates
|
|
18105
|
+
description: 'Validates against mutating props, state, and other values that [are immutable](https://react.dev/reference/rules/components-and-hooks-must-be-pure#props-and-state-are-immutable)',
|
|
18099
18106
|
recommended: true,
|
|
18100
18107
|
};
|
|
18101
18108
|
}
|
|
@@ -18111,7 +18118,9 @@ function getRuleForCategory(category) {
|
|
|
18111
18118
|
return {
|
|
18112
18119
|
category,
|
|
18113
18120
|
name: 'preserve-manual-memoization',
|
|
18114
|
-
description: 'Validates that existing manual memoized is preserved by the compiler'
|
|
18121
|
+
description: 'Validates that existing manual memoized is preserved by the compiler. ' +
|
|
18122
|
+
'React Compiler will only compile components and hooks if its inference ' +
|
|
18123
|
+
'[matches or exceeds the existing manual memoization](https://react.dev/learn/react-compiler/introduction#what-should-i-do-about-usememo-usecallback-and-reactmemo)',
|
|
18115
18124
|
recommended: true,
|
|
18116
18125
|
};
|
|
18117
18126
|
}
|
|
@@ -18119,7 +18128,7 @@ function getRuleForCategory(category) {
|
|
|
18119
18128
|
return {
|
|
18120
18129
|
category,
|
|
18121
18130
|
name: 'purity',
|
|
18122
|
-
description: 'Validates that
|
|
18131
|
+
description: 'Validates that [components/hooks are pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure) by checking that they do not call known-impure functions',
|
|
18123
18132
|
recommended: true,
|
|
18124
18133
|
};
|
|
18125
18134
|
}
|
|
@@ -18127,7 +18136,7 @@ function getRuleForCategory(category) {
|
|
|
18127
18136
|
return {
|
|
18128
18137
|
category,
|
|
18129
18138
|
name: 'refs',
|
|
18130
|
-
description: 'Validates correct usage of refs, not reading/writing during render',
|
|
18139
|
+
description: 'Validates correct usage of refs, not reading/writing during render. See the "pitfalls" section in [`useRef()` usage](https://react.dev/reference/react/useRef#usage)',
|
|
18131
18140
|
recommended: true,
|
|
18132
18141
|
};
|
|
18133
18142
|
}
|
|
@@ -18135,7 +18144,7 @@ function getRuleForCategory(category) {
|
|
|
18135
18144
|
return {
|
|
18136
18145
|
category,
|
|
18137
18146
|
name: 'set-state-in-render',
|
|
18138
|
-
description: 'Validates against setting state during render',
|
|
18147
|
+
description: 'Validates against setting state during render, which can trigger additional renders and potential infinite render loops',
|
|
18139
18148
|
recommended: true,
|
|
18140
18149
|
};
|
|
18141
18150
|
}
|
|
@@ -18143,7 +18152,7 @@ function getRuleForCategory(category) {
|
|
|
18143
18152
|
return {
|
|
18144
18153
|
category,
|
|
18145
18154
|
name: 'static-components',
|
|
18146
|
-
description: 'Validates that components are static, not recreated every render',
|
|
18155
|
+
description: 'Validates that components are static, not recreated every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering',
|
|
18147
18156
|
recommended: true,
|
|
18148
18157
|
};
|
|
18149
18158
|
}
|
|
@@ -18175,7 +18184,7 @@ function getRuleForCategory(category) {
|
|
|
18175
18184
|
return {
|
|
18176
18185
|
category,
|
|
18177
18186
|
name: 'unsupported-syntax',
|
|
18178
|
-
description: 'Validates against syntax that we do not plan to support',
|
|
18187
|
+
description: 'Validates against syntax that we do not plan to support in React Compiler',
|
|
18179
18188
|
recommended: true,
|
|
18180
18189
|
};
|
|
18181
18190
|
}
|
|
@@ -18183,7 +18192,7 @@ function getRuleForCategory(category) {
|
|
|
18183
18192
|
return {
|
|
18184
18193
|
category,
|
|
18185
18194
|
name: 'use-memo',
|
|
18186
|
-
description: 'Validates usage of the useMemo() hook',
|
|
18195
|
+
description: 'Validates usage of the useMemo() hook against common mistakes. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',
|
|
18187
18196
|
recommended: true,
|
|
18188
18197
|
};
|
|
18189
18198
|
}
|
|
@@ -19458,7 +19467,8 @@ function printType(type) {
|
|
|
19458
19467
|
return `:T${type.kind}<${type.shapeId}>`;
|
|
19459
19468
|
}
|
|
19460
19469
|
else if (type.kind === 'Function' && type.shapeId != null) {
|
|
19461
|
-
|
|
19470
|
+
const returnType = printType(type.return);
|
|
19471
|
+
return `:T${type.kind}<${type.shapeId}>()${returnType !== '' ? `: ${returnType}` : ''}`;
|
|
19462
19472
|
}
|
|
19463
19473
|
else {
|
|
19464
19474
|
return `:T${type.kind}`;
|
|
@@ -40443,6 +40453,18 @@ function computeSignatureForInstruction(context, env, instr) {
|
|
|
40443
40453
|
});
|
|
40444
40454
|
}
|
|
40445
40455
|
}
|
|
40456
|
+
for (const prop of value.props) {
|
|
40457
|
+
if (prop.kind === 'JsxAttribute' &&
|
|
40458
|
+
prop.place.identifier.type.kind === 'Function' &&
|
|
40459
|
+
(isJsxType(prop.place.identifier.type.return) ||
|
|
40460
|
+
(prop.place.identifier.type.return.kind === 'Phi' &&
|
|
40461
|
+
prop.place.identifier.type.return.operands.some(operand => isJsxType(operand))))) {
|
|
40462
|
+
effects.push({
|
|
40463
|
+
kind: 'Render',
|
|
40464
|
+
place: prop.place,
|
|
40465
|
+
});
|
|
40466
|
+
}
|
|
40467
|
+
}
|
|
40446
40468
|
}
|
|
40447
40469
|
break;
|
|
40448
40470
|
}
|
|
@@ -46736,6 +46758,14 @@ class Unifier {
|
|
|
46736
46758
|
if (type.kind === 'Phi') {
|
|
46737
46759
|
return { kind: 'Phi', operands: type.operands.map(o => this.get(o)) };
|
|
46738
46760
|
}
|
|
46761
|
+
if (type.kind === 'Function') {
|
|
46762
|
+
return {
|
|
46763
|
+
kind: 'Function',
|
|
46764
|
+
isConstructor: type.isConstructor,
|
|
46765
|
+
shapeId: type.shapeId,
|
|
46766
|
+
return: this.get(type.return),
|
|
46767
|
+
};
|
|
46768
|
+
}
|
|
46739
46769
|
return type;
|
|
46740
46770
|
}
|
|
46741
46771
|
}
|
|
@@ -17984,14 +17984,20 @@ var ErrorCategory;
|
|
|
17984
17984
|
ErrorCategory["Fire"] = "Fire";
|
|
17985
17985
|
ErrorCategory["FBT"] = "FBT";
|
|
17986
17986
|
})(ErrorCategory || (ErrorCategory = {}));
|
|
17987
|
+
const RULE_NAME_PATTERN = /^[a-z]+(-[a-z]+)*$/;
|
|
17987
17988
|
function getRuleForCategory(category) {
|
|
17989
|
+
const rule = getRuleForCategoryImpl(category);
|
|
17990
|
+
invariant(RULE_NAME_PATTERN.test(rule.name), `Invalid rule name, got '${rule.name}' but rules must match ${RULE_NAME_PATTERN.toString()}`);
|
|
17991
|
+
return rule;
|
|
17992
|
+
}
|
|
17993
|
+
function getRuleForCategoryImpl(category) {
|
|
17988
17994
|
switch (category) {
|
|
17989
17995
|
case ErrorCategory.AutomaticEffectDependencies: {
|
|
17990
17996
|
return {
|
|
17991
17997
|
category,
|
|
17992
17998
|
name: 'automatic-effect-dependencies',
|
|
17993
17999
|
description: 'Verifies that automatic effect dependencies are compiled if opted-in',
|
|
17994
|
-
recommended:
|
|
18000
|
+
recommended: false,
|
|
17995
18001
|
};
|
|
17996
18002
|
}
|
|
17997
18003
|
case ErrorCategory.CapitalizedCalls: {
|
|
@@ -18006,7 +18012,7 @@ function getRuleForCategory(category) {
|
|
|
18006
18012
|
return {
|
|
18007
18013
|
category,
|
|
18008
18014
|
name: 'config',
|
|
18009
|
-
description: 'Validates the configuration',
|
|
18015
|
+
description: 'Validates the compiler configuration options',
|
|
18010
18016
|
recommended: true,
|
|
18011
18017
|
};
|
|
18012
18018
|
}
|
|
@@ -18030,7 +18036,7 @@ function getRuleForCategory(category) {
|
|
|
18030
18036
|
return {
|
|
18031
18037
|
category,
|
|
18032
18038
|
name: 'set-state-in-effect',
|
|
18033
|
-
description: 'Validates against calling setState synchronously in an effect',
|
|
18039
|
+
description: 'Validates against calling setState synchronously in an effect, which can lead to re-renders that degrade performance',
|
|
18034
18040
|
recommended: true,
|
|
18035
18041
|
};
|
|
18036
18042
|
}
|
|
@@ -18038,7 +18044,7 @@ function getRuleForCategory(category) {
|
|
|
18038
18044
|
return {
|
|
18039
18045
|
category,
|
|
18040
18046
|
name: 'error-boundaries',
|
|
18041
|
-
description: 'Validates usage of error boundaries instead of try/catch for errors in
|
|
18047
|
+
description: 'Validates usage of error boundaries instead of try/catch for errors in child components',
|
|
18042
18048
|
recommended: true,
|
|
18043
18049
|
};
|
|
18044
18050
|
}
|
|
@@ -18062,7 +18068,7 @@ function getRuleForCategory(category) {
|
|
|
18062
18068
|
return {
|
|
18063
18069
|
category,
|
|
18064
18070
|
name: 'gating',
|
|
18065
|
-
description: 'Validates configuration of gating mode',
|
|
18071
|
+
description: 'Validates configuration of [gating mode](https://react.dev/reference/react-compiler/gating)',
|
|
18066
18072
|
recommended: true,
|
|
18067
18073
|
};
|
|
18068
18074
|
}
|
|
@@ -18070,7 +18076,8 @@ function getRuleForCategory(category) {
|
|
|
18070
18076
|
return {
|
|
18071
18077
|
category,
|
|
18072
18078
|
name: 'globals',
|
|
18073
|
-
description: 'Validates against assignment/mutation of globals during render'
|
|
18079
|
+
description: 'Validates against assignment/mutation of globals during render, part of ensuring that ' +
|
|
18080
|
+
'[side effects must render outside of render](https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
|
|
18074
18081
|
recommended: true,
|
|
18075
18082
|
};
|
|
18076
18083
|
}
|
|
@@ -18086,7 +18093,7 @@ function getRuleForCategory(category) {
|
|
|
18086
18093
|
return {
|
|
18087
18094
|
category,
|
|
18088
18095
|
name: 'immutability',
|
|
18089
|
-
description: 'Validates
|
|
18096
|
+
description: 'Validates against mutating props, state, and other values that [are immutable](https://react.dev/reference/rules/components-and-hooks-must-be-pure#props-and-state-are-immutable)',
|
|
18090
18097
|
recommended: true,
|
|
18091
18098
|
};
|
|
18092
18099
|
}
|
|
@@ -18102,7 +18109,9 @@ function getRuleForCategory(category) {
|
|
|
18102
18109
|
return {
|
|
18103
18110
|
category,
|
|
18104
18111
|
name: 'preserve-manual-memoization',
|
|
18105
|
-
description: 'Validates that existing manual memoized is preserved by the compiler'
|
|
18112
|
+
description: 'Validates that existing manual memoized is preserved by the compiler. ' +
|
|
18113
|
+
'React Compiler will only compile components and hooks if its inference ' +
|
|
18114
|
+
'[matches or exceeds the existing manual memoization](https://react.dev/learn/react-compiler/introduction#what-should-i-do-about-usememo-usecallback-and-reactmemo)',
|
|
18106
18115
|
recommended: true,
|
|
18107
18116
|
};
|
|
18108
18117
|
}
|
|
@@ -18110,7 +18119,7 @@ function getRuleForCategory(category) {
|
|
|
18110
18119
|
return {
|
|
18111
18120
|
category,
|
|
18112
18121
|
name: 'purity',
|
|
18113
|
-
description: 'Validates that
|
|
18122
|
+
description: 'Validates that [components/hooks are pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure) by checking that they do not call known-impure functions',
|
|
18114
18123
|
recommended: true,
|
|
18115
18124
|
};
|
|
18116
18125
|
}
|
|
@@ -18118,7 +18127,7 @@ function getRuleForCategory(category) {
|
|
|
18118
18127
|
return {
|
|
18119
18128
|
category,
|
|
18120
18129
|
name: 'refs',
|
|
18121
|
-
description: 'Validates correct usage of refs, not reading/writing during render',
|
|
18130
|
+
description: 'Validates correct usage of refs, not reading/writing during render. See the "pitfalls" section in [`useRef()` usage](https://react.dev/reference/react/useRef#usage)',
|
|
18122
18131
|
recommended: true,
|
|
18123
18132
|
};
|
|
18124
18133
|
}
|
|
@@ -18126,7 +18135,7 @@ function getRuleForCategory(category) {
|
|
|
18126
18135
|
return {
|
|
18127
18136
|
category,
|
|
18128
18137
|
name: 'set-state-in-render',
|
|
18129
|
-
description: 'Validates against setting state during render',
|
|
18138
|
+
description: 'Validates against setting state during render, which can trigger additional renders and potential infinite render loops',
|
|
18130
18139
|
recommended: true,
|
|
18131
18140
|
};
|
|
18132
18141
|
}
|
|
@@ -18134,7 +18143,7 @@ function getRuleForCategory(category) {
|
|
|
18134
18143
|
return {
|
|
18135
18144
|
category,
|
|
18136
18145
|
name: 'static-components',
|
|
18137
|
-
description: 'Validates that components are static, not recreated every render',
|
|
18146
|
+
description: 'Validates that components are static, not recreated every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering',
|
|
18138
18147
|
recommended: true,
|
|
18139
18148
|
};
|
|
18140
18149
|
}
|
|
@@ -18166,7 +18175,7 @@ function getRuleForCategory(category) {
|
|
|
18166
18175
|
return {
|
|
18167
18176
|
category,
|
|
18168
18177
|
name: 'unsupported-syntax',
|
|
18169
|
-
description: 'Validates against syntax that we do not plan to support',
|
|
18178
|
+
description: 'Validates against syntax that we do not plan to support in React Compiler',
|
|
18170
18179
|
recommended: true,
|
|
18171
18180
|
};
|
|
18172
18181
|
}
|
|
@@ -18174,7 +18183,7 @@ function getRuleForCategory(category) {
|
|
|
18174
18183
|
return {
|
|
18175
18184
|
category,
|
|
18176
18185
|
name: 'use-memo',
|
|
18177
|
-
description: 'Validates usage of the useMemo() hook',
|
|
18186
|
+
description: 'Validates usage of the useMemo() hook against common mistakes. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',
|
|
18178
18187
|
recommended: true,
|
|
18179
18188
|
};
|
|
18180
18189
|
}
|
|
@@ -19449,7 +19458,8 @@ function printType(type) {
|
|
|
19449
19458
|
return `:T${type.kind}<${type.shapeId}>`;
|
|
19450
19459
|
}
|
|
19451
19460
|
else if (type.kind === 'Function' && type.shapeId != null) {
|
|
19452
|
-
|
|
19461
|
+
const returnType = printType(type.return);
|
|
19462
|
+
return `:T${type.kind}<${type.shapeId}>()${returnType !== '' ? `: ${returnType}` : ''}`;
|
|
19453
19463
|
}
|
|
19454
19464
|
else {
|
|
19455
19465
|
return `:T${type.kind}`;
|
|
@@ -40270,6 +40280,18 @@ function computeSignatureForInstruction(context, env, instr) {
|
|
|
40270
40280
|
});
|
|
40271
40281
|
}
|
|
40272
40282
|
}
|
|
40283
|
+
for (const prop of value.props) {
|
|
40284
|
+
if (prop.kind === 'JsxAttribute' &&
|
|
40285
|
+
prop.place.identifier.type.kind === 'Function' &&
|
|
40286
|
+
(isJsxType(prop.place.identifier.type.return) ||
|
|
40287
|
+
(prop.place.identifier.type.return.kind === 'Phi' &&
|
|
40288
|
+
prop.place.identifier.type.return.operands.some(operand => isJsxType(operand))))) {
|
|
40289
|
+
effects.push({
|
|
40290
|
+
kind: 'Render',
|
|
40291
|
+
place: prop.place,
|
|
40292
|
+
});
|
|
40293
|
+
}
|
|
40294
|
+
}
|
|
40273
40295
|
}
|
|
40274
40296
|
break;
|
|
40275
40297
|
}
|
|
@@ -46563,6 +46585,14 @@ class Unifier {
|
|
|
46563
46585
|
if (type.kind === 'Phi') {
|
|
46564
46586
|
return { kind: 'Phi', operands: type.operands.map(o => this.get(o)) };
|
|
46565
46587
|
}
|
|
46588
|
+
if (type.kind === 'Function') {
|
|
46589
|
+
return {
|
|
46590
|
+
kind: 'Function',
|
|
46591
|
+
isConstructor: type.isConstructor,
|
|
46592
|
+
shapeId: type.shapeId,
|
|
46593
|
+
return: this.get(type.return),
|
|
46594
|
+
};
|
|
46595
|
+
}
|
|
46566
46596
|
return type;
|
|
46567
46597
|
}
|
|
46568
46598
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks",
|
|
3
3
|
"description": "ESLint rules for React Hooks",
|
|
4
|
-
"version": "6.1.0-canary-
|
|
4
|
+
"version": "6.1.0-canary-33a1095d-20250827",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/facebook/react.git",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@babel/core": "^7.24.4",
|
|
43
43
|
"@babel/parser": "^7.24.4",
|
|
44
|
-
"@babel/plugin-
|
|
44
|
+
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
|
45
45
|
"hermes-parser": "^0.25.1",
|
|
46
46
|
"zod": "^3.22.4",
|
|
47
47
|
"zod-validation-error": "^3.0.3"
|