@@ -1267,23 +1267,64 @@ function updateMutableSource<Source, Snapshot>(
1267
1267
function mountSyncExternalStore< T > (
1268
1268
subscribe: (() => void ) => ( ) => void ,
1269
1269
getSnapshot : ( ) => T ,
1270
+ getServerSnapshot ?: ( ) => T ,
1270
1271
) : T {
1271
1272
const fiber = currentlyRenderingFiber ;
1272
1273
const hook = mountWorkInProgressHook ( ) ;
1273
- // Read the current snapshot from the store on every render. This breaks the
1274
- // normal rules of React, and only works because store updates are
1275
- // always synchronous.
1276
- const nextSnapshot = getSnapshot ( ) ;
1277
- if ( __DEV__ ) {
1278
- if ( ! didWarnUncachedGetSnapshot ) {
1279
- if ( nextSnapshot !== getSnapshot ( ) ) {
1280
- console . error (
1281
- 'The result of getSnapshot should be cached to avoid an infinite loop' ,
1282
- ) ;
1283
- didWarnUncachedGetSnapshot = true ;
1274
+
1275
+ let nextSnapshot ;
1276
+ const isHydrating = getIsHydrating ( ) ;
1277
+ if ( isHydrating ) {
1278
+ if ( getServerSnapshot === undefined ) {
1279
+ invariant (
1280
+ false ,
1281
+ 'Missing getServerSnapshot, which is required for ' +
1282
+ 'server-rendered content. Will revert to client rendering.' ,
1283
+ ) ;
1284
+ }
1285
+ nextSnapshot = getServerSnapshot ( ) ;
1286
+ if ( __DEV__ ) {
1287
+ if ( ! didWarnUncachedGetSnapshot ) {
1288
+ if ( nextSnapshot !== getServerSnapshot ( ) ) {
1289
+ console . error (
1290
+ 'The result of getServerSnapshot should be cached to avoid an infinite loop' ,
1291
+ ) ;
1292
+ didWarnUncachedGetSnapshot = true ;
1293
+ }
1284
1294
}
1285
1295
}
1296
+ } else {
1297
+ nextSnapshot = getSnapshot ( ) ;
1298
+ if ( __DEV__ ) {
1299
+ if ( ! didWarnUncachedGetSnapshot ) {
1300
+ if ( nextSnapshot !== getSnapshot ( ) ) {
1301
+ console . error (
1302
+ 'The result of getSnapshot should be cached to avoid an infinite loop' ,
1303
+ ) ;
1304
+ didWarnUncachedGetSnapshot = true ;
1305
+ }
1306
+ }
1307
+ }
1308
+ // Unless we're rendering a blocking lane, schedule a consistency check.
1309
+ // Right before committing, we will walk the tree and check if any of the
1310
+ // stores were mutated.
1311
+ //
1312
+ // We won't do this if we're hydrating server-rendered content, because if
1313
+ // the content is stale, it's already visible anyway. Instead we'll patch
1314
+ // it up in a passive effect.
1315
+ const root : FiberRoot | null = getWorkInProgressRoot ( ) ;
1316
+ invariant (
1317
+ root !== null ,
1318
+ 'Expected a work - in - progress root . This is a bug in React . Please file an issue . ',
1319
+ ) ;
1320
+ if ( ! includesBlockingLane ( root , renderLanes ) ) {
1321
+ pushStoreConsistencyCheck ( fiber , getSnapshot , nextSnapshot ) ;
1322
+ }
1286
1323
}
1324
+
1325
+ // Read the current snapshot from the store on every render. This breaks the
1326
+ // normal rules of React, and only works because store updates are
1327
+ // always synchronous.
1287
1328
hook . memoizedState = nextSnapshot ;
1288
1329
const inst : StoreInstance < T > = {
1289
1330
value : nextSnapshot ,
@@ -1309,24 +1350,13 @@ function mountSyncExternalStore<T>(
1309
1350
null,
1310
1351
);
1311
1352
1312
- // Unless we're rendering a blocking lane, schedule a consistency check. Right
1313
- // before committing, we will walk the tree and check if any of the stores
1314
- // were mutated.
1315
- const root : FiberRoot | null = getWorkInProgressRoot ( ) ;
1316
- invariant (
1317
- root !== null ,
1318
- 'Expected a work-in-progress root. This is a bug in React. Please file an issue.' ,
1319
- ) ;
1320
- if ( ! includesBlockingLane ( root , renderLanes ) ) {
1321
- pushStoreConsistencyCheck ( fiber , getSnapshot , nextSnapshot ) ;
1322
- }
1323
-
1324
1353
return nextSnapshot;
1325
1354
}
1326
1355
1327
1356
function updateSyncExternalStore < T > (
1328
1357
subscribe: (() => void ) => ( ) => void ,
1329
1358
getSnapshot : ( ) => T ,
1359
+ getServerSnapshot ?: ( ) => T ,
1330
1360
) : T {
1331
1361
const fiber = currentlyRenderingFiber ;
1332
1362
const hook = updateWorkInProgressHook ( ) ;
@@ -2577,10 +2607,11 @@ if (__DEV__) {
2577
2607
useSyncExternalStore< T > (
2578
2608
subscribe: (() => void ) => ( ) => void ,
2579
2609
getSnapshot : ( ) => T ,
2610
+ getServerSnapshot ?: ( ) => T ,
2580
2611
) : T {
2581
2612
currentHookNameInDev = 'useSyncExternalStore' ;
2582
2613
mountHookTypesDev ( ) ;
2583
- return mountSyncExternalStore ( subscribe , getSnapshot ) ;
2614
+ return mountSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
2584
2615
} ,
2585
2616
useOpaqueIdentifier(): OpaqueIDType | void {
2586
2617
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -2717,10 +2748,11 @@ if (__DEV__) {
2717
2748
useSyncExternalStore< T > (
2718
2749
subscribe: (() => void ) => ( ) => void ,
2719
2750
getSnapshot : ( ) => T ,
2751
+ getServerSnapshot ?: ( ) => T ,
2720
2752
) : T {
2721
2753
currentHookNameInDev = 'useSyncExternalStore' ;
2722
2754
updateHookTypesDev ( ) ;
2723
- return mountSyncExternalStore ( subscribe , getSnapshot ) ;
2755
+ return mountSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
2724
2756
} ,
2725
2757
useOpaqueIdentifier(): OpaqueIDType | void {
2726
2758
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -2857,10 +2889,11 @@ if (__DEV__) {
2857
2889
useSyncExternalStore< T > (
2858
2890
subscribe: (() => void ) => ( ) => void ,
2859
2891
getSnapshot : ( ) => T ,
2892
+ getServerSnapshot ?: ( ) => T ,
2860
2893
) : T {
2861
2894
currentHookNameInDev = 'useSyncExternalStore' ;
2862
2895
updateHookTypesDev ( ) ;
2863
- return updateSyncExternalStore ( subscribe , getSnapshot ) ;
2896
+ return updateSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
2864
2897
} ,
2865
2898
useOpaqueIdentifier(): OpaqueIDType | void {
2866
2899
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -2998,10 +3031,11 @@ if (__DEV__) {
2998
3031
useSyncExternalStore< T > (
2999
3032
subscribe: (() => void ) => ( ) => void ,
3000
3033
getSnapshot : ( ) => T ,
3034
+ getServerSnapshot ?: ( ) => T ,
3001
3035
) : T {
3002
3036
currentHookNameInDev = 'useSyncExternalStore' ;
3003
3037
updateHookTypesDev ( ) ;
3004
- return updateSyncExternalStore ( subscribe , getSnapshot ) ;
3038
+ return updateSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
3005
3039
} ,
3006
3040
useOpaqueIdentifier(): OpaqueIDType | void {
3007
3041
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -3153,11 +3187,12 @@ if (__DEV__) {
3153
3187
useSyncExternalStore< T > (
3154
3188
subscribe: (() => void ) => ( ) => void ,
3155
3189
getSnapshot : ( ) => T ,
3190
+ getServerSnapshot ?: ( ) => T ,
3156
3191
) : T {
3157
3192
currentHookNameInDev = 'useSyncExternalStore' ;
3158
3193
warnInvalidHookAccess ( ) ;
3159
3194
mountHookTypesDev ( ) ;
3160
- return mountSyncExternalStore ( subscribe , getSnapshot ) ;
3195
+ return mountSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
3161
3196
} ,
3162
3197
useOpaqueIdentifier(): OpaqueIDType | void {
3163
3198
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -3310,11 +3345,12 @@ if (__DEV__) {
3310
3345
useSyncExternalStore< T > (
3311
3346
subscribe: (() => void ) => ( ) => void ,
3312
3347
getSnapshot : ( ) => T ,
3348
+ getServerSnapshot ?: ( ) => T ,
3313
3349
) : T {
3314
3350
currentHookNameInDev = 'useSyncExternalStore' ;
3315
3351
warnInvalidHookAccess ( ) ;
3316
3352
updateHookTypesDev ( ) ;
3317
- return updateSyncExternalStore ( subscribe , getSnapshot ) ;
3353
+ return updateSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
3318
3354
} ,
3319
3355
useOpaqueIdentifier(): OpaqueIDType | void {
3320
3356
currentHookNameInDev = 'useOpaqueIdentifier' ;
@@ -3468,11 +3504,12 @@ if (__DEV__) {
3468
3504
useSyncExternalStore< T > (
3469
3505
subscribe: (() => void ) => ( ) => void ,
3470
3506
getSnapshot : ( ) => T ,
3507
+ getServerSnapshot ?: ( ) => T ,
3471
3508
) : T {
3472
3509
currentHookNameInDev = 'useSyncExternalStore' ;
3473
3510
warnInvalidHookAccess ( ) ;
3474
3511
updateHookTypesDev ( ) ;
3475
- return updateSyncExternalStore ( subscribe , getSnapshot ) ;
3512
+ return updateSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
3476
3513
} ,
3477
3514
useOpaqueIdentifier(): OpaqueIDType | void {
3478
3515
currentHookNameInDev = 'useOpaqueIdentifier' ;
0 commit comments