Skip to content
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

Possible optimization to useSyncExternalStore's withSelector #24884

Open
dutziworks opened this issue Jul 9, 2022 · 5 comments
Open

Possible optimization to useSyncExternalStore's withSelector #24884

dutziworks opened this issue Jul 9, 2022 · 5 comments

Comments

@dutziworks
Copy link

dutziworks commented Jul 9, 2022

const prevSnapshot: Snapshot = (memoizedSnapshot: any);
const prevSelection: Selection = (memoizedSelection: any);
if (is(prevSnapshot, nextSnapshot)) {
// The snapshot is the same as last time. Reuse the previous selection.
return prevSelection;
}
// The snapshot has changed, so we need to compute a new selection.
const nextSelection = selector(nextSnapshot);
// If a custom isEqual function is provided, use that to check if the data
// has changed. If it hasn't, return the previous selection. That signals
// to React that the selections are conceptually equal, and we can bail
// out of rendering.
if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
return prevSelection;
}
memoizedSnapshot = nextSnapshot;
memoizedSelection = nextSelection;
return nextSelection;

Hey, isn't line 89 in block above supposed to be right before line 78?

I mean, if prevSnapshot and nextSnapshot are not equal, but prevSelection and nextSelection are equal, shouldn't we at least update memoizedSnapshot to be equal to nextSnapshot?

That way, in the next run of this callback, we at least don't run selector and isEqual again.

I may be missing something here, but I did make that change in our, pretty hefty, code base and all the tests passed and I got a nice performance boost.

const prevSnapshot: Snapshot = (memoizedSnapshot: any);
const prevSelection: Selection = (memoizedSelection: any);

if (is(prevSnapshot, nextSnapshot)) {
  // The snapshot is the same as last time. Reuse the previous selection.
  return prevSelection;
}

memoizedSnapshot = nextSnapshot;

// The snapshot has changed, so we need to compute a new selection.
const nextSelection = selector(nextSnapshot);

// If a custom isEqual function is provided, use that to check if the data
// has changed. If it hasn't, return the previous selection. That signals
// to React that the selections are conceptually equal, and we can bail
// out of rendering.
if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
  return prevSelection;
}

memoizedSelection = nextSelection;
return nextSelection;
@karankulshrestha
Copy link

I will fix it please give me

@karankulshrestha
Copy link

please assign me

@jellevoost
Copy link

Next to the optimization mentioned, there is another issue this resolves: reduxjs/react-redux#1981
If you use a shared store that changes often, with selectors that always return an equal result, it will keep copies of that old store alive as they are never updated.

Copy link

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!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
@markerikson
Copy link
Contributor

Still worth looking at.

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants