Skip to content

Conversation

@josephsavona
Copy link
Member

@josephsavona josephsavona commented Nov 25, 2025

In ValidateExhaustiveDependencies, I previously changed to allow extraneous dependencies as long as they were non-reactive. Here we make that more precise, and distinguish between values that are definitely referenced in the memo function but optional as dependencies vs values that are not even referenced in the memo function. The latter now error as extraneous even if they're non-reactive. This also turned up a case where constant-folded primitives could show up as false positives of the latter category, so now we track manual deps which quality for constant folding and don't error on them.


Stack created with Sapling. Best reviewed with ReviewStack.

@meta-cla meta-cla bot added the CLA Signed label Nov 25, 2025
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Nov 25, 2025
@josephsavona josephsavona requested a review from mofeiZ November 25, 2025 00:31
@josephsavona josephsavona force-pushed the pr35204 branch 2 times, most recently from 842865e to 6bb6f89 Compare November 25, 2025 00:37
In ValidateExhaustiveDependencies, I previously changed to allow extraneous dependencies as long as they were non-reactive. Here we make that more precise, and distinguish between values that are definitely referenced in the memo function but optional as dependencies vs values that are not even referenced in the memo function. The latter now error as extraneous even if they're non-reactive. This also turned up a case where constant-folded primitives could show up as false positives of the latter category, so now we track manual deps which quality for constant folding and don't error on them.
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
Component = Stringify;

Component;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like an existing bug where DCE isn't cleaning this up

Comment on lines +244 to +249
const isOptionalDependency =
!reactive.has(inferredDependency.identifier.id) &&
(isStableType(inferredDependency.identifier) ||
isPrimitiveType(inferredDependency.identifier));
if (hasMatchingManualDependency || isOptionalDependency) {
continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this switches us back to special casing non-reactive deps allowed by exhaustive-deps rule.

This code should now bail out (right)?

hook useHook() {
  const obj = {};
  return useMemo(() => obj, []);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested in a follow-up

Comment on lines +267 to +270
/*
* Constant primitives can get constant-folded, which means we won't
* see a LoadLocal for the value within the memo function.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, thanks for the explanation

const x = useMemo(() => {
return [state];
// error: `setState` is a stable type, but not actually referenced
}, [state, setState]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

Copy link
Contributor

@mofeiZ mofeiZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Could we add something like this as a fixture?

// error.fixture
hook useHook() {
  const obj = {};
  return useMemo(() => obj, []);
}

// error.fixture2
hook useHook() {
  // here, obj goes unmemoized
  const obj = {};
  useHook();
  obj.x = 4;
  return useMemo(() => obj, []);
}

@josephsavona josephsavona merged commit d39a1d6 into main Nov 25, 2025
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants