Skip to content

Commit 77912d9

Browse files
authored
Wire up the native API for useSyncExternalStore (#22237)
Adds useSyncExternalStore to the internal dispatcher, and exports the native API from the React package without yet implementing it.
1 parent 031abd2 commit 77912d9

17 files changed

+311
-61
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

+8
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ function useMutableSource<Source, Snapshot>(
265265
return value;
266266
}
267267

268+
function useSyncExternalStore<T>(
269+
subscribe: (() => void) => () => void,
270+
getSnapshot: () => T,
271+
): T {
272+
throw new Error('Not yet implemented');
273+
}
274+
268275
function useTransition(): [boolean, (() => void) => void] {
269276
// useTransition() composes multiple hooks internally.
270277
// Advance the current hook index the same number of times
@@ -326,6 +333,7 @@ const Dispatcher: DispatcherType = {
326333
useState,
327334
useTransition,
328335
useMutableSource,
336+
useSyncExternalStore,
329337
useDeferredValue,
330338
useOpaqueIdentifier,
331339
};

packages/react-dom/src/server/ReactPartialRendererHooks.js

+8
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,13 @@ function useMutableSource<Source, Snapshot>(
462462
return getSnapshot(source._source);
463463
}
464464

465+
function useSyncExternalStore<T>(
466+
subscribe: (() => void) => () => void,
467+
getSnapshot: () => T,
468+
): T {
469+
throw new Error('Not yet implemented');
470+
}
471+
465472
function useDeferredValue<T>(value: T): T {
466473
resolveCurrentlyRenderingComponent();
467474
return value;
@@ -514,6 +521,7 @@ export const Dispatcher: DispatcherType = {
514521
useOpaqueIdentifier,
515522
// Subscriptions are not setup in a server environment.
516523
useMutableSource,
524+
useSyncExternalStore,
517525
};
518526

519527
if (enableCache) {

packages/react-reconciler/src/ReactFiberHooks.new.js

+77
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,20 @@ function updateMutableSource<Source, Snapshot>(
12421242
return useMutableSource(hook, source, getSnapshot, subscribe);
12431243
}
12441244

1245+
function mountSyncExternalStore<T>(
1246+
subscribe: (() => void) => () => void,
1247+
getSnapshot: () => T,
1248+
): T {
1249+
throw new Error('Not yet implemented');
1250+
}
1251+
1252+
function updateSyncExternalStore<T>(
1253+
subscribe: (() => void) => () => void,
1254+
getSnapshot: () => T,
1255+
): T {
1256+
throw new Error('Not yet implemented');
1257+
}
1258+
12451259
function mountState<S>(
12461260
initialState: (() => S) | S,
12471261
): [S, Dispatch<BasicStateAction<S>>] {
@@ -2079,6 +2093,7 @@ export const ContextOnlyDispatcher: Dispatcher = {
20792093
useDeferredValue: throwInvalidHookError,
20802094
useTransition: throwInvalidHookError,
20812095
useMutableSource: throwInvalidHookError,
2096+
useSyncExternalStore: throwInvalidHookError,
20822097
useOpaqueIdentifier: throwInvalidHookError,
20832098

20842099
unstable_isNewReconciler: enableNewReconciler,
@@ -2104,6 +2119,7 @@ const HooksDispatcherOnMount: Dispatcher = {
21042119
useDeferredValue: mountDeferredValue,
21052120
useTransition: mountTransition,
21062121
useMutableSource: mountMutableSource,
2122+
useSyncExternalStore: mountSyncExternalStore,
21072123
useOpaqueIdentifier: mountOpaqueIdentifier,
21082124

21092125
unstable_isNewReconciler: enableNewReconciler,
@@ -2129,6 +2145,7 @@ const HooksDispatcherOnUpdate: Dispatcher = {
21292145
useDeferredValue: updateDeferredValue,
21302146
useTransition: updateTransition,
21312147
useMutableSource: updateMutableSource,
2148+
useSyncExternalStore: updateSyncExternalStore,
21322149
useOpaqueIdentifier: updateOpaqueIdentifier,
21332150

21342151
unstable_isNewReconciler: enableNewReconciler,
@@ -2154,6 +2171,7 @@ const HooksDispatcherOnRerender: Dispatcher = {
21542171
useDeferredValue: rerenderDeferredValue,
21552172
useTransition: rerenderTransition,
21562173
useMutableSource: updateMutableSource,
2174+
useSyncExternalStore: mountSyncExternalStore,
21572175
useOpaqueIdentifier: rerenderOpaqueIdentifier,
21582176

21592177
unstable_isNewReconciler: enableNewReconciler,
@@ -2302,6 +2320,14 @@ if (__DEV__) {
23022320
mountHookTypesDev();
23032321
return mountMutableSource(source, getSnapshot, subscribe);
23042322
},
2323+
useSyncExternalStore<T>(
2324+
subscribe: (() => void) => () => void,
2325+
getSnapshot: () => T,
2326+
): T {
2327+
currentHookNameInDev = 'useSyncExternalStore';
2328+
mountHookTypesDev();
2329+
return mountSyncExternalStore(subscribe, getSnapshot);
2330+
},
23052331
useOpaqueIdentifier(): OpaqueIDType | void {
23062332
currentHookNameInDev = 'useOpaqueIdentifier';
23072333
mountHookTypesDev();
@@ -2426,6 +2452,14 @@ if (__DEV__) {
24262452
updateHookTypesDev();
24272453
return mountMutableSource(source, getSnapshot, subscribe);
24282454
},
2455+
useSyncExternalStore<T>(
2456+
subscribe: (() => void) => () => void,
2457+
getSnapshot: () => T,
2458+
): T {
2459+
currentHookNameInDev = 'useSyncExternalStore';
2460+
updateHookTypesDev();
2461+
return mountSyncExternalStore(subscribe, getSnapshot);
2462+
},
24292463
useOpaqueIdentifier(): OpaqueIDType | void {
24302464
currentHookNameInDev = 'useOpaqueIdentifier';
24312465
updateHookTypesDev();
@@ -2550,6 +2584,14 @@ if (__DEV__) {
25502584
updateHookTypesDev();
25512585
return updateMutableSource(source, getSnapshot, subscribe);
25522586
},
2587+
useSyncExternalStore<T>(
2588+
subscribe: (() => void) => () => void,
2589+
getSnapshot: () => T,
2590+
): T {
2591+
currentHookNameInDev = 'useSyncExternalStore';
2592+
updateHookTypesDev();
2593+
return updateSyncExternalStore(subscribe, getSnapshot);
2594+
},
25532595
useOpaqueIdentifier(): OpaqueIDType | void {
25542596
currentHookNameInDev = 'useOpaqueIdentifier';
25552597
updateHookTypesDev();
@@ -2675,6 +2717,14 @@ if (__DEV__) {
26752717
updateHookTypesDev();
26762718
return updateMutableSource(source, getSnapshot, subscribe);
26772719
},
2720+
useSyncExternalStore<T>(
2721+
subscribe: (() => void) => () => void,
2722+
getSnapshot: () => T,
2723+
): T {
2724+
currentHookNameInDev = 'useSyncExternalStore';
2725+
updateHookTypesDev();
2726+
return updateSyncExternalStore(subscribe, getSnapshot);
2727+
},
26782728
useOpaqueIdentifier(): OpaqueIDType | void {
26792729
currentHookNameInDev = 'useOpaqueIdentifier';
26802730
updateHookTypesDev();
@@ -2813,6 +2863,15 @@ if (__DEV__) {
28132863
mountHookTypesDev();
28142864
return mountMutableSource(source, getSnapshot, subscribe);
28152865
},
2866+
useSyncExternalStore<T>(
2867+
subscribe: (() => void) => () => void,
2868+
getSnapshot: () => T,
2869+
): T {
2870+
currentHookNameInDev = 'useSyncExternalStore';
2871+
warnInvalidHookAccess();
2872+
mountHookTypesDev();
2873+
return mountSyncExternalStore(subscribe, getSnapshot);
2874+
},
28162875
useOpaqueIdentifier(): OpaqueIDType | void {
28172876
currentHookNameInDev = 'useOpaqueIdentifier';
28182877
warnInvalidHookAccess();
@@ -2952,6 +3011,15 @@ if (__DEV__) {
29523011
updateHookTypesDev();
29533012
return updateMutableSource(source, getSnapshot, subscribe);
29543013
},
3014+
useSyncExternalStore<T>(
3015+
subscribe: (() => void) => () => void,
3016+
getSnapshot: () => T,
3017+
): T {
3018+
currentHookNameInDev = 'useSyncExternalStore';
3019+
warnInvalidHookAccess();
3020+
updateHookTypesDev();
3021+
return updateSyncExternalStore(subscribe, getSnapshot);
3022+
},
29553023
useOpaqueIdentifier(): OpaqueIDType | void {
29563024
currentHookNameInDev = 'useOpaqueIdentifier';
29573025
warnInvalidHookAccess();
@@ -3092,6 +3160,15 @@ if (__DEV__) {
30923160
updateHookTypesDev();
30933161
return updateMutableSource(source, getSnapshot, subscribe);
30943162
},
3163+
useSyncExternalStore<T>(
3164+
subscribe: (() => void) => () => void,
3165+
getSnapshot: () => T,
3166+
): T {
3167+
currentHookNameInDev = 'useSyncExternalStore';
3168+
warnInvalidHookAccess();
3169+
updateHookTypesDev();
3170+
return updateSyncExternalStore(subscribe, getSnapshot);
3171+
},
30953172
useOpaqueIdentifier(): OpaqueIDType | void {
30963173
currentHookNameInDev = 'useOpaqueIdentifier';
30973174
warnInvalidHookAccess();

packages/react-reconciler/src/ReactFiberHooks.old.js

+77
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,20 @@ function updateMutableSource<Source, Snapshot>(
12421242
return useMutableSource(hook, source, getSnapshot, subscribe);
12431243
}
12441244

1245+
function mountSyncExternalStore<T>(
1246+
subscribe: (() => void) => () => void,
1247+
getSnapshot: () => T,
1248+
): T {
1249+
throw new Error('Not yet implemented');
1250+
}
1251+
1252+
function updateSyncExternalStore<T>(
1253+
subscribe: (() => void) => () => void,
1254+
getSnapshot: () => T,
1255+
): T {
1256+
throw new Error('Not yet implemented');
1257+
}
1258+
12451259
function mountState<S>(
12461260
initialState: (() => S) | S,
12471261
): [S, Dispatch<BasicStateAction<S>>] {
@@ -2079,6 +2093,7 @@ export const ContextOnlyDispatcher: Dispatcher = {
20792093
useDeferredValue: throwInvalidHookError,
20802094
useTransition: throwInvalidHookError,
20812095
useMutableSource: throwInvalidHookError,
2096+
useSyncExternalStore: throwInvalidHookError,
20822097
useOpaqueIdentifier: throwInvalidHookError,
20832098

20842099
unstable_isNewReconciler: enableNewReconciler,
@@ -2104,6 +2119,7 @@ const HooksDispatcherOnMount: Dispatcher = {
21042119
useDeferredValue: mountDeferredValue,
21052120
useTransition: mountTransition,
21062121
useMutableSource: mountMutableSource,
2122+
useSyncExternalStore: mountSyncExternalStore,
21072123
useOpaqueIdentifier: mountOpaqueIdentifier,
21082124

21092125
unstable_isNewReconciler: enableNewReconciler,
@@ -2129,6 +2145,7 @@ const HooksDispatcherOnUpdate: Dispatcher = {
21292145
useDeferredValue: updateDeferredValue,
21302146
useTransition: updateTransition,
21312147
useMutableSource: updateMutableSource,
2148+
useSyncExternalStore: updateSyncExternalStore,
21322149
useOpaqueIdentifier: updateOpaqueIdentifier,
21332150

21342151
unstable_isNewReconciler: enableNewReconciler,
@@ -2154,6 +2171,7 @@ const HooksDispatcherOnRerender: Dispatcher = {
21542171
useDeferredValue: rerenderDeferredValue,
21552172
useTransition: rerenderTransition,
21562173
useMutableSource: updateMutableSource,
2174+
useSyncExternalStore: mountSyncExternalStore,
21572175
useOpaqueIdentifier: rerenderOpaqueIdentifier,
21582176

21592177
unstable_isNewReconciler: enableNewReconciler,
@@ -2302,6 +2320,14 @@ if (__DEV__) {
23022320
mountHookTypesDev();
23032321
return mountMutableSource(source, getSnapshot, subscribe);
23042322
},
2323+
useSyncExternalStore<T>(
2324+
subscribe: (() => void) => () => void,
2325+
getSnapshot: () => T,
2326+
): T {
2327+
currentHookNameInDev = 'useSyncExternalStore';
2328+
mountHookTypesDev();
2329+
return mountSyncExternalStore(subscribe, getSnapshot);
2330+
},
23052331
useOpaqueIdentifier(): OpaqueIDType | void {
23062332
currentHookNameInDev = 'useOpaqueIdentifier';
23072333
mountHookTypesDev();
@@ -2426,6 +2452,14 @@ if (__DEV__) {
24262452
updateHookTypesDev();
24272453
return mountMutableSource(source, getSnapshot, subscribe);
24282454
},
2455+
useSyncExternalStore<T>(
2456+
subscribe: (() => void) => () => void,
2457+
getSnapshot: () => T,
2458+
): T {
2459+
currentHookNameInDev = 'useSyncExternalStore';
2460+
updateHookTypesDev();
2461+
return mountSyncExternalStore(subscribe, getSnapshot);
2462+
},
24292463
useOpaqueIdentifier(): OpaqueIDType | void {
24302464
currentHookNameInDev = 'useOpaqueIdentifier';
24312465
updateHookTypesDev();
@@ -2550,6 +2584,14 @@ if (__DEV__) {
25502584
updateHookTypesDev();
25512585
return updateMutableSource(source, getSnapshot, subscribe);
25522586
},
2587+
useSyncExternalStore<T>(
2588+
subscribe: (() => void) => () => void,
2589+
getSnapshot: () => T,
2590+
): T {
2591+
currentHookNameInDev = 'useSyncExternalStore';
2592+
updateHookTypesDev();
2593+
return updateSyncExternalStore(subscribe, getSnapshot);
2594+
},
25532595
useOpaqueIdentifier(): OpaqueIDType | void {
25542596
currentHookNameInDev = 'useOpaqueIdentifier';
25552597
updateHookTypesDev();
@@ -2675,6 +2717,14 @@ if (__DEV__) {
26752717
updateHookTypesDev();
26762718
return updateMutableSource(source, getSnapshot, subscribe);
26772719
},
2720+
useSyncExternalStore<T>(
2721+
subscribe: (() => void) => () => void,
2722+
getSnapshot: () => T,
2723+
): T {
2724+
currentHookNameInDev = 'useSyncExternalStore';
2725+
updateHookTypesDev();
2726+
return updateSyncExternalStore(subscribe, getSnapshot);
2727+
},
26782728
useOpaqueIdentifier(): OpaqueIDType | void {
26792729
currentHookNameInDev = 'useOpaqueIdentifier';
26802730
updateHookTypesDev();
@@ -2813,6 +2863,15 @@ if (__DEV__) {
28132863
mountHookTypesDev();
28142864
return mountMutableSource(source, getSnapshot, subscribe);
28152865
},
2866+
useSyncExternalStore<T>(
2867+
subscribe: (() => void) => () => void,
2868+
getSnapshot: () => T,
2869+
): T {
2870+
currentHookNameInDev = 'useSyncExternalStore';
2871+
warnInvalidHookAccess();
2872+
mountHookTypesDev();
2873+
return mountSyncExternalStore(subscribe, getSnapshot);
2874+
},
28162875
useOpaqueIdentifier(): OpaqueIDType | void {
28172876
currentHookNameInDev = 'useOpaqueIdentifier';
28182877
warnInvalidHookAccess();
@@ -2952,6 +3011,15 @@ if (__DEV__) {
29523011
updateHookTypesDev();
29533012
return updateMutableSource(source, getSnapshot, subscribe);
29543013
},
3014+
useSyncExternalStore<T>(
3015+
subscribe: (() => void) => () => void,
3016+
getSnapshot: () => T,
3017+
): T {
3018+
currentHookNameInDev = 'useSyncExternalStore';
3019+
warnInvalidHookAccess();
3020+
updateHookTypesDev();
3021+
return updateSyncExternalStore(subscribe, getSnapshot);
3022+
},
29553023
useOpaqueIdentifier(): OpaqueIDType | void {
29563024
currentHookNameInDev = 'useOpaqueIdentifier';
29573025
warnInvalidHookAccess();
@@ -3092,6 +3160,15 @@ if (__DEV__) {
30923160
updateHookTypesDev();
30933161
return updateMutableSource(source, getSnapshot, subscribe);
30943162
},
3163+
useSyncExternalStore<T>(
3164+
subscribe: (() => void) => () => void,
3165+
getSnapshot: () => T,
3166+
): T {
3167+
currentHookNameInDev = 'useSyncExternalStore';
3168+
warnInvalidHookAccess();
3169+
updateHookTypesDev();
3170+
return updateSyncExternalStore(subscribe, getSnapshot);
3171+
},
30953172
useOpaqueIdentifier(): OpaqueIDType | void {
30963173
currentHookNameInDev = 'useOpaqueIdentifier';
30973174
warnInvalidHookAccess();

packages/react-reconciler/src/ReactInternalTypes.js

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type HookType =
4141
| 'useDeferredValue'
4242
| 'useTransition'
4343
| 'useMutableSource'
44+
| 'useSyncExternalStore'
4445
| 'useOpaqueIdentifier'
4546
| 'useCacheRefresh';
4647

@@ -304,6 +305,10 @@ export type Dispatcher = {|
304305
getSnapshot: MutableSourceGetSnapshotFn<Source, Snapshot>,
305306
subscribe: MutableSourceSubscribeFn<Source, Snapshot>,
306307
): Snapshot,
308+
useSyncExternalStore<T>(
309+
subscribe: (() => void) => () => void,
310+
getSnapshot: () => T,
311+
): T,
307312
useOpaqueIdentifier(): any,
308313
useCacheRefresh?: () => <T>(?() => T, ?T) => void,
309314

0 commit comments

Comments
 (0)