[Fresh] Don't ignore dependencies for render phase updates #16574
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
During a Fresh update, we ignore dependencies. We let the effects re-run, even if deps are
[]
, and free the memo'd values.This is important because it prevents us from referencing stale code. For example, if we edit top-level
computeExpensive
, we still wantuseMemo(() => computeExpensive(), [])
to re-evaluate.Sometimes this may cause problems, but arguably this points to other flaws in components or Hooks that should be fixed regardless.
There is a failure case though. Generally, while components shouldn’t rely on
useMemo
for semantics, there is still an expectation that memo chains can “settle”. For example,useSubscription
does a render-phase update if its arguments differ from its state:react/packages/use-subscription/src/useSubscription.js
Lines 42 to 45 in 0da7bd0
It has to rely on something like
useMemo
in the calling code to keep the source eventually stable.The problem with our current approach is that during a Fresh update, dependencies are ignored completely. So even with
useMemo
, things never truly “settle”. This breaks the pattern relied upon byuseSubscription
, and likely, other similar mechanisms.The fix is to only ignore dependencies during the first render after the patch. By that point it has run, all memo'd values have been recreated with fresh code. So it makes sense that we can turn off the cache busting flag for all subsequent render-phase updates of this component, thus letting it settle. This fixes the infinite loop in the regression test I've added.