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

Fork updateSyncExternalStore impl in update and rerender #25650

Closed
wants to merge 3 commits into from

Conversation

eps1lon
Copy link
Collaborator

@eps1lon eps1lon commented Nov 8, 2022

Summary

Follow-up to #25578.

Applied the same pattern as used in useDeferredValue implementations.

How did you test this change?

  • yarn test
  • CI

@sizebot
Copy link

sizebot commented Nov 8, 2022

Comparing: 1e3e30d...168f118

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js +0.10% 153.65 kB 153.81 kB +0.05% 48.90 kB 48.92 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js +0.10% 155.57 kB 155.73 kB +0.05% 49.51 kB 49.54 kB
facebook-www/ReactDOM-prod.classic.js +0.12% 530.46 kB 531.10 kB +0.06% 94.67 kB 94.73 kB
facebook-www/ReactDOM-prod.modern.js +0.12% 515.71 kB 516.36 kB +0.06% 92.49 kB 92.55 kB
facebook-www/ReactDOMForked-prod.classic.js +0.12% 530.46 kB 531.10 kB +0.06% 94.67 kB 94.73 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 168f118

@@ -2798,7 +2836,7 @@ const HooksDispatcherOnRerender: Dispatcher = {
useDeferredValue: rerenderDeferredValue,
useTransition: rerenderTransition,
useMutableSource: updateMutableSource,
useSyncExternalStore: updateSyncExternalStore,
useSyncExternalStore: rerenderSyncExternalStore,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to do this same change for the other "on rerender" dispatchers

Copy link
Collaborator

@acdlite acdlite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the only place you missed

useSyncExternalStore<T>(
subscribe: (() => void) => () => void,
getSnapshot: () => T,
getServerSnapshot?: () => T,
): T {
currentHookNameInDev = 'useSyncExternalStore';
warnInvalidHookAccess();
updateHookTypesDev();
return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
},

@eps1lon eps1lon force-pushed the fix/uSES-rerender-impl branch from 36a0806 to 68da82a Compare November 8, 2022 21:51
@eps1lon eps1lon requested a review from acdlite November 8, 2022 22:04
const prevSnapshot =
currentHook === null
? // This is a rerender during a mount.
hook.memoizedState
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I know this is equivalent to what #25650 did, but now that I look closer I think this is wrong for initial render. prevSnapshot should represent what's currently rendered on the screen. If there is no previous snapshot, then we should always schedule a commit effect. That's why mountSyncExternalStore always schedules an effect, without checking first.

So I think if currentHook is null, this should call mountSyncExternalStore instead.

Initial render should always mount an effect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm wouldn't this also mean we no longer use the client snapshot when we rerender during hydration?

Tried

function rerenderSyncExternalStore<T>(
  subscribe: (() => void) => () => void,
  getSnapshot: () => T,
  getServerSnapshot?: () => T,
): T {
  if (currentHook === null) {
    return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
  } else {
    const hook = updateWorkInProgressHook();
    // This is a rerender during an update.
    return updateSyncExternalStoreImpl(
      hook,
      hook.memoizedState,
      subscribe,
      getSnapshot,
      getServerSnapshot,
    );
  }
}

and this leads to

 FAIL  packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js
  ● Shared useSyncExternalStore behavior (shim and built-in) › regression test for #23150

    Rendered more hooks than during the previous render.

Copy link
Collaborator

@acdlite acdlite Nov 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to call updateWorkInProgressHook and then pass the hook as an argument. The rest of the logic is the same.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried that, still not working. I don't really understand how the pieces fit together here. Seems to me we're conditionally using hooks and the error is expected.

@eps1lon eps1lon force-pushed the fix/uSES-rerender-impl branch from 168f118 to 1e3d745 Compare April 16, 2023 09:48
@react-sizebot
Copy link

Comparing: b600620...1e3d745

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js +0.10% 164.42 kB 164.58 kB +0.06% 51.69 kB 51.72 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js +0.09% 166.86 kB 167.02 kB +0.06% 52.34 kB 52.38 kB
facebook-www/ReactDOM-prod.classic.js +0.11% 564.45 kB 565.10 kB +0.07% 99.40 kB 99.47 kB
facebook-www/ReactDOM-prod.modern.js +0.12% 548.24 kB 548.88 kB +0.07% 96.71 kB 96.78 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 1e3d745

sophiebits added a commit that referenced this pull request May 12, 2023
Previously, we'd call and use getSnapshot on the second render resulting
in `Warning: Text content did not match. Server: "Nay!" Client: "Yay!"`
and then `Error: Text content does not match server-rendered HTML.`.

Fixes #26095. Closes #26113. Closes #25650.

---------

Co-authored-by: eps1lon <[email protected]>
github-actions bot pushed a commit that referenced this pull request May 12, 2023
Previously, we'd call and use getSnapshot on the second render resulting
in `Warning: Text content did not match. Server: "Nay!" Client: "Yay!"`
and then `Error: Text content does not match server-rendered HTML.`.

Fixes #26095. Closes #26113. Closes #25650.

---------

Co-authored-by: eps1lon <[email protected]>

DiffTrain build for [4cd7065](4cd7065)
@eps1lon eps1lon deleted the fix/uSES-rerender-impl branch March 14, 2024 14:15
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Previously, we'd call and use getSnapshot on the second render resulting
in `Warning: Text content did not match. Server: "Nay!" Client: "Yay!"`
and then `Error: Text content does not match server-rendered HTML.`.

Fixes facebook#26095. Closes facebook#26113. Closes facebook#25650.

---------

Co-authored-by: eps1lon <[email protected]>
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
Previously, we'd call and use getSnapshot on the second render resulting
in `Warning: Text content did not match. Server: "Nay!" Client: "Yay!"`
and then `Error: Text content does not match server-rendered HTML.`.

Fixes #26095. Closes #26113. Closes #25650.

---------

Co-authored-by: eps1lon <[email protected]>

DiffTrain build for commit 4cd7065.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants