7
7
* @flow
8
8
*/
9
9
10
+ import type { Dispatcher as DispatcherType } from 'react-reconciler/src/ReactInternalTypes' ;
10
11
import type {
11
12
Destination ,
12
13
Chunk ,
@@ -29,12 +30,24 @@ import {
29
30
30
31
import {
31
32
REACT_BLOCK_TYPE ,
32
- REACT_SERVER_BLOCK_TYPE ,
33
33
REACT_ELEMENT_TYPE ,
34
+ REACT_DEBUG_TRACING_MODE_TYPE ,
35
+ REACT_FORWARD_REF_TYPE ,
34
36
REACT_FRAGMENT_TYPE ,
35
37
REACT_LAZY_TYPE ,
38
+ REACT_LEGACY_HIDDEN_TYPE ,
39
+ REACT_MEMO_TYPE ,
40
+ REACT_OFFSCREEN_TYPE ,
41
+ REACT_PROFILER_TYPE ,
42
+ REACT_SCOPE_TYPE ,
43
+ REACT_SERVER_BLOCK_TYPE ,
44
+ REACT_STRICT_MODE_TYPE ,
45
+ REACT_SUSPENSE_TYPE ,
46
+ REACT_SUSPENSE_LIST_TYPE ,
36
47
} from 'shared/ReactSymbols' ;
37
48
49
+ import * as React from 'react' ;
50
+ import ReactSharedInternals from 'shared/ReactSharedInternals' ;
38
51
import invariant from 'shared/invariant' ;
39
52
40
53
type ReactJSONValue =
@@ -74,6 +87,8 @@ export type Request = {
74
87
toJSON : ( key : string , value : ReactModel ) => ReactJSONValue ,
75
88
} ;
76
89
90
+ const ReactCurrentDispatcher = ReactSharedInternals . ReactCurrentDispatcher ;
91
+
77
92
export function createRequest (
78
93
model : ReactModel ,
79
94
destination : Destination ,
@@ -110,11 +125,33 @@ function attemptResolveElement(element: React$Element<any>): ReactModel {
110
125
return [ REACT_ELEMENT_TYPE , type , element . key , element . props ] ;
111
126
} else if ( type [ 0 ] === REACT_SERVER_BLOCK_TYPE ) {
112
127
return [ REACT_ELEMENT_TYPE , type , element . key , element . props ] ;
113
- } else if ( type === REACT_FRAGMENT_TYPE ) {
128
+ } else if (
129
+ type === REACT_FRAGMENT_TYPE ||
130
+ type === REACT_STRICT_MODE_TYPE ||
131
+ type === REACT_PROFILER_TYPE ||
132
+ type === REACT_SCOPE_TYPE ||
133
+ type === REACT_DEBUG_TRACING_MODE_TYPE ||
134
+ type === REACT_LEGACY_HIDDEN_TYPE ||
135
+ type === REACT_OFFSCREEN_TYPE ||
136
+ // TODO: These are temporary shims
137
+ // and we'll want a different behavior.
138
+ type === REACT_SUSPENSE_TYPE ||
139
+ type === REACT_SUSPENSE_LIST_TYPE
140
+ ) {
114
141
return element . props . children ;
115
- } else {
116
- invariant ( false , 'Unsupported type.' ) ;
142
+ } else if ( type != null && typeof type === 'object ') {
143
+ switch ( type . $$typeof ) {
144
+ case REACT_FORWARD_REF_TYPE : {
145
+ const render = type . render ;
146
+ return render ( props , undefined ) ;
147
+ }
148
+ case REACT_MEMO_TYPE : {
149
+ const nextChildren = React . createElement ( type . type , element . props ) ;
150
+ return attemptResolveElement ( nextChildren ) ;
151
+ }
152
+ }
117
153
}
154
+ invariant ( false , 'Unsupported type.' ) ;
118
155
}
119
156
120
157
function pingSegment ( request : Request , segment : Segment ) : void {
@@ -236,9 +273,11 @@ export function resolveModelToJSON(
236
273
value !== null &&
237
274
value . $$typeof === REACT_ELEMENT_TYPE
238
275
) {
276
+ const prevDispatcher = ReactCurrentDispatcher . current ;
239
277
// TODO: Concatenate keys of parents onto children.
240
278
const element : React$Element < any > = (value: any);
241
279
try {
280
+ ReactCurrentDispatcher . current = Dispatcher ;
242
281
// Attempt to render the server component.
243
282
value = attemptResolveElement ( element ) ;
244
283
} catch (x) {
@@ -253,6 +292,8 @@ export function resolveModelToJSON(
253
292
// Something errored. Don't bother encoding anything up to here.
254
293
throw x ;
255
294
}
295
+ } finally {
296
+ ReactCurrentDispatcher . current = prevDispatcher ;
256
297
}
257
298
}
258
299
@@ -378,3 +419,33 @@ export function startFlowing(request: Request): void {
378
419
request . flowing = true ;
379
420
flushCompletedChunks ( request ) ;
380
421
}
422
+
423
+ function unsupportedHook ( ) : void {
424
+ invariant ( false , 'This Hook is not supported in Server Components.' ) ;
425
+ }
426
+
427
+ const Dispatcher : DispatcherType = {
428
+ useMemo < T > ( nextCreate : ( ) = > T ) : T {
429
+ return nextCreate ( ) ;
430
+ } ,
431
+ useCallback < T > ( callback : T ) : T {
432
+ return callback ;
433
+ } ,
434
+ useDebugValue ( ) : void { } ,
435
+ useDeferredValue < T > ( value : T ) : T {
436
+ return value ;
437
+ } ,
438
+ useTransition ( ) : [ ( callback : ( ) = > void ) => void , boolean ] {
439
+ return[ ( ) => { } , false ] ;
440
+ } ,
441
+ readContext : ( unsupportedHook : any ) ,
442
+ useContext : ( unsupportedHook : any ) ,
443
+ useReducer : ( unsupportedHook : any ) ,
444
+ useRef : ( unsupportedHook : any ) ,
445
+ useState : ( unsupportedHook : any ) ,
446
+ useLayoutEffect : ( unsupportedHook : any ) ,
447
+ useImperativeHandle : ( unsupportedHook : any ) ,
448
+ useEffect : ( unsupportedHook : any ) ,
449
+ useOpaqueIdentifier : ( unsupportedHook : any ) ,
450
+ useMutableSource : ( unsupportedHook : any ) ,
451
+ } ;
0 commit comments