[compiler] Adjustments to exhaustive deps messages, disable the lint rule (#35192)
Similar to ValidateHookUsage, we implement this check in the compiler for safety but (for now) continue to rely on the existing rule for actually reporting errors to users. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35192). * #35201 * #35202 * __->__ #35192
Joseph Savona committed
Nov 24, 2025 at 12:20 UTC
9599e7a787cce2a41c35d783d45a160dfebab277
4 files changed
+20
-10
compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts
+9
-1
@@ -1067,7 +1067,15 @@ function getRuleForCategoryImpl(category: ErrorCategory): LintRule {
1067
name: 'memo-dependencies',
1068
description:
1069
'Validates that useMemo() and useCallback() specify comprehensive dependencies without extraneous values. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',
1070
- preset: LintRulePreset.RecommendedLatest,
1070
+ /**
1071
+ * TODO: the "MemoDependencies" rule largely reimplements the "exhaustive-deps" non-compiler rule,
1072
+ * allowing the compiler to ensure it does not regress change behavior due to different dependencies.
1073
+ * We previously relied on the source having ESLint suppressions for any exhaustive-deps violations,
1074
+ * but it's more reliable to verify it within the compiler.
1075
+ *
1076
+ * Long-term we should de-duplicate these implementations.
1077
+ */
1078
+ preset: LintRulePreset.Off,
1079
};
1080
}
1081
case ErrorCategory.IncompatibleLibrary: {
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts
+5
-3
@@ -303,9 +303,11 @@ function runWithEnvironment(
303
inferReactivePlaces(hir);
304
log({kind: 'hir', name: 'InferReactivePlaces', value: hir});
305
306
- if (env.config.validateExhaustiveMemoizationDependencies) {
307
- // NOTE: this relies on reactivity inference running first
308
- validateExhaustiveDependencies(hir).unwrap();
306
+ if (env.enableValidations) {
307
+ if (env.config.validateExhaustiveMemoizationDependencies) {
308
+ // NOTE: this relies on reactivity inference running first
309
+ validateExhaustiveDependencies(hir).unwrap();
310
+ }
311
}
312
313
rewriteInstructionKindsBasedOnReassignment(hir);
compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts
+2
-2
@@ -284,7 +284,7 @@ export function validateExhaustiveDependencies(
284
if (missing.length !== 0) {
285
const diagnostic = CompilerDiagnostic.create({
286
category: ErrorCategory.MemoDependencies,
287
- reason: 'Found non-exhaustive dependencies',
287
+ reason: 'Found missing memoization dependencies',
288
description:
289
'Missing dependencies can cause a value not to update when those inputs change, ' +
290
'resulting in stale UI',
@@ -309,7 +309,7 @@ export function validateExhaustiveDependencies(
309
reason: 'Found unnecessary memoization dependencies',
310
description:
311
'Unnecessary dependencies can cause a value to update more often than necessary, ' +
312
- 'which can cause effects to run more than expected',
312
+ 'causing performance regressions and effects to fire more often than expected',
313
});
314
diagnostic.withDetails({
315
kind: 'error',
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-exhaustive-deps.expect.md
+4
-4
@@ -53,7 +53,7 @@ function Component({x, y, z}) {
53
```
54
Found 4 errors:
55
56
-Error: Found non-exhaustive dependencies
56
+Error: Found missing memoization dependencies
57
58
Missing dependencies can cause a value not to update when those inputs change, resulting in stale UI.
59
@@ -66,7 +66,7 @@ error.invalid-exhaustive-deps.ts:7:11
66
9 | }, [x?.y.z?.a.b]);
67
10 | const b = useMemo(() => {
68
69
-Error: Found non-exhaustive dependencies
69
+Error: Found missing memoization dependencies
70
71
Missing dependencies can cause a value not to update when those inputs change, resulting in stale UI.
72
@@ -81,7 +81,7 @@ error.invalid-exhaustive-deps.ts:15:11
81
82
Error: Found unnecessary memoization dependencies
83
84
-Unnecessary dependencies can cause a value to update more often than necessary, which can cause effects to run more than expected.
84
+Unnecessary dependencies can cause a value to update more often than necessary, causing performance regressions and effects to fire more often than expected.
85
86
error.invalid-exhaustive-deps.ts:31:5
87
29 | return [];
@@ -92,7 +92,7 @@ error.invalid-exhaustive-deps.ts:31:5
92
33 | const ref2 = useRef(null);
93
34 | const ref = z ? ref1 : ref2;
94
95
-Error: Found non-exhaustive dependencies
95
+Error: Found missing memoization dependencies
96
97
Missing dependencies can cause a value not to update when those inputs change, resulting in stale UI.
98