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