Skip to content

Possible optimization to useSyncExternalStore's withSelector #24884

Closed as not planned
@dutziworks

Description

@dutziworks

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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Resolution: StaleAutomatically closed due to inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions