-
Notifications
You must be signed in to change notification settings - Fork 48.9k
[fresh] Reset useMemoCache when size changes #30663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. ghstack-source-id: 2f17b95 Pull Request resolved: #30663
Comparing: dd8e0ba...e007738 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: Expand to show
|
data = memoCache.data[memoCache.index] = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
data[i] = REACT_MEMO_CACHE_SENTINEL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative approach might be to append a debug property on the fiber during fast refresh to reset the cache only when Fresh actually kicks in. That has the advantage of resetting the cache during a refresh even when cache size is the same (ie new code happened to result in the same number of cache slots)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be the better approach to me.
- React shouldn't be throwing prod-only errors.
- Feels very likely there are types of changes where the memo size doesn't change (e.g. some literal such as a style is updated in the component)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does useMemo do if its implementation changes? Does it just keep its cache entry? Seems like it would need to reset for the same reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useMemo always drops the cache on hot reload. Seems like we should do the same for uMC? We assume memoization is not essential for the logic and can be reconstructed. This also tests that the component logic is resilient to it somewhat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. ghstack-source-id: 48c5b9c Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. ghstack-source-id: bffbd19 Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. ghstack-source-id: 48c5b9c Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. ghstack-source-id: 3fa6248 Pull Request resolved: #30663
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing in prod for something that works in dev can lead to problems. I think we might need to either a) specifically limit this to fast refresh in dev (so that it errors otherwise) or b) just reset even in prod.
But I can see the argument that since you are never supposed to use this API directly, that it's maybe fine for it to have different behavior in dev/prod.
@josephsavona Yeah I was kinda torn about it but I was thinking that there should be no case ever where the cache size would change in between renders in prod, so it's better to error early. Alternatively (as you also pointed out in (b)) we can always reset the cache if the size changes in any environment, which would then eliminate the dev/prod divergence |
Per offline discussion let's go with resetting whenever the size changes. Seems like we're agreed that the ideal way to do this is for React to get a signal that a particular component fast refreshed and to reset the cache only then. But let's save that for a follow-up. |
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. However, for consistency we continue to reset the cache as well. ghstack-source-id: b295a5d Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. However, for consistency we continue to reset the cache as well. ghstack-source-id: b295a5d Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. However, for consistency we continue to reset the cache as well. ghstack-source-id: 7f343a7 Pull Request resolved: #30663
During development when adding or removing code, it is common for the cache size to vary between refreshes. Rather than warn like before, let's simply and safely reset the cache completely whenever its size changes between renders. In practice, in non-development environments full invalidation should never happen since the only consumer of uMC is compiled code – which always emits a static call to uMC with a fixed size. However, for consistency we continue to reset the cache as well. ghstack-source-id: 440a899 Pull Request resolved: #30663
@josephsavona updated |
Why is it not sufficient to always throw away the cache on hot reload? Unless I’m missing something, that’s what we do for useMemo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think #30700 should take care of this, assuming the special case is only needed for Fast Refresh.
Closing in favor of #30700 |
Stacked on #30662. Alternative to #30663 and #30677. During a Fast Refresh, we always want to evict the memo cache, same as we do with normal `useMemo`. The mechanism used by `useMemo` and other Hooks is this module-level variable: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L304-L307 which has DEV-only behavior as if the dependencies are always different: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L451-L460 The `useMemoCache` Hook doesn't use a dependency array but conceptually I think we want the same behavior. ## Test Plan The test passes. --------- Co-authored-by: Lauren Tan <poteto@users.noreply.github.com>
Stacked on #30662. Alternative to #30663 and #30677. During a Fast Refresh, we always want to evict the memo cache, same as we do with normal `useMemo`. The mechanism used by `useMemo` and other Hooks is this module-level variable: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L304-L307 which has DEV-only behavior as if the dependencies are always different: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L451-L460 The `useMemoCache` Hook doesn't use a dependency array but conceptually I think we want the same behavior. ## Test Plan The test passes. --------- Co-authored-by: Lauren Tan <poteto@users.noreply.github.com> DiffTrain build for [7e8a06c](7e8a06c)
Stacked on #30662. Alternative to #30663 and #30677. During a Fast Refresh, we always want to evict the memo cache, same as we do with normal `useMemo`. The mechanism used by `useMemo` and other Hooks is this module-level variable: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L304-L307 which has DEV-only behavior as if the dependencies are always different: https://github.com/facebook/react/blob/fca5d655d78917400a2722287351c20938166669/packages/react-reconciler/src/ReactFiberHooks.js#L451-L460 The `useMemoCache` Hook doesn't use a dependency array but conceptually I think we want the same behavior. ## Test Plan The test passes. --------- Co-authored-by: Lauren Tan <poteto@users.noreply.github.com> DiffTrain build for commit 7e8a06c.
Stack from ghstack (oldest at bottom):
During development when adding or removing code, it is common for the
cache size to vary between refreshes. Rather than warn like before,
let's simply and safely reset the cache completely whenever its size
changes between renders. In practice, in non-development environments
full invalidation should never happen since the only consumer of uMC is
compiled code – which always emits a static call to uMC with a fixed
size. However, for consistency we continue to reset the cache as well.