diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index cf8086b075aa..7747a25c858e 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -2471,7 +2471,7 @@ const HooksDispatcherOnRerender: Dispatcher = { useDeferredValue: rerenderDeferredValue, useTransition: rerenderTransition, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: enableNewReconciler, diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index ff2aff6720e1..d7137e8cd7f6 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -2471,7 +2471,7 @@ const HooksDispatcherOnRerender: Dispatcher = { useDeferredValue: rerenderDeferredValue, useTransition: rerenderTransition, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: enableNewReconciler, diff --git a/packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js b/packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js index 5af9e9767ab0..cb3a40aa13ab 100644 --- a/packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js +++ b/packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js @@ -745,6 +745,33 @@ describe('Shared useSyncExternalStore behavior (shim and built-in)', () => { }); }); + test('regression test for #23150', async () => { + const store = createExternalStore('Initial'); + + function App() { + const text = useSyncExternalStore(store.subscribe, store.getState); + const [derivedText, setDerivedText] = useState(text); + useEffect(() => {}, []); + if (derivedText !== text.toUpperCase()) { + setDerivedText(text.toUpperCase()); + } + return ; + } + + const container = document.createElement('div'); + const root = createRoot(container); + await act(() => root.render()); + + expect(Scheduler).toHaveYielded(['INITIAL']); + expect(container.textContent).toEqual('INITIAL'); + + await act(() => { + store.set('Updated'); + }); + expect(Scheduler).toHaveYielded(['UPDATED']); + expect(container.textContent).toEqual('UPDATED'); + }); + // The selector implementation uses the lazy ref initialization pattern // @gate !(enableUseRefAccessWarning && __DEV__) test('compares selection to rendered selection even if selector changes', async () => {