You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Within useSyncExternalStoreWithSelector there is currently a bug that will keep old references to the used store alive if you use an immutable store in combination with selectors that always result in the same result. This can lead to excessive memory usage while this is not needed. I've noticed this behavior in combination with react-redux, but also managed to reproduce it without react-redux to figure out exactly what was going on. (I've reported this at the react-redux repo as well reduxjs/react-redux#1981)
React version: 18.2.0
Steps To Reproduce
Since the reproduction is fairly complicated I've created a sandbox with details on how to reproduce including a minimal working sample that also includes the reproduction steps within that exact example.
But in summary, it is reproducible using the following steps:
You will need an immutable store that you will use with your selector (new copy every store update)
You will need a stable custom isEqual function and selector that are not created in-line
The store needs some property (e.g. a string) that is easily found within memory snapshots. (It helps to include a timestamp within this property that updates on store change)
You will need to print a value from the store within your main component, to show the most recent result of the store.
You will need a component that uses a stable selector to select a stale value (something that never changes) from the store
Next up you need to update the store and add an additional copy of the previous component (the one created in step 5.)
Repeat this a few times
Take a memory snapshot and notice there are multiple copies of the store present in memoizedSnapshots of the different components. You can see this by searching on the property you defined in step 3.
Whenever the result of getSnapshot() is changed, but the result of the selector() has not, the memoized reference to the old result of getSnapshot() is not updated, resulting in unnecessary copies of the store used alive. Whenever you have a fairly large store that is shared between quite a bunch of selectors, especially with components that are mounted at a later timestamp and use selectors that have stale data, you could end up with an ever increasing amount of store references resulting in high memory usage.
The expected behavior
Whenever the result of getSnapshot() is changed, but the result of the selector() has not, the memoized reference to the old result of getSnapshot() is updated correctly, preventing unnecessary copies from being kept alive. This should not impact the behavior of useSyncExternalStoreWithSelector but should/can reduce the memory footprint of applications using this.
The text was updated successfully, but these errors were encountered:
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Within
useSyncExternalStoreWithSelector
there is currently a bug that will keep old references to the used store alive if you use an immutable store in combination with selectors that always result in the same result. This can lead to excessive memory usage while this is not needed. I've noticed this behavior in combination with react-redux, but also managed to reproduce it without react-redux to figure out exactly what was going on. (I've reported this at the react-redux repo as well reduxjs/react-redux#1981)React version: 18.2.0
Steps To Reproduce
Since the reproduction is fairly complicated I've created a sandbox with details on how to reproduce including a minimal working sample that also includes the reproduction steps within that exact example.
But in summary, it is reproducible using the following steps:
Link to code example:
https://codesandbox.io/s/fervent-ives-0vm9es?file=/src/App.jsx
The current behavior
The expected behavior
useSyncExternalStoreWithSelector
but should/can reduce the memory footprint of applications using this.The text was updated successfully, but these errors were encountered: