Skip to content

Commit fa03206

Browse files
authored
Remove _ctor field from Lazy components (#18217)
* This type is all wrong and nothing cares because it's all any * Refine Flow types of Lazy Components We can type each condition. * Remove _ctor field from Lazy components This field is not needed because it's only used before we've initialized, and we don't have anything else to store before we've initialized. * Check for _ctor in case it's an older isomorphic that created it We try not to break across minors but it's no guarantee. * Move types and constants from shared to isomorphic The "react" package owns the data structure of the Lazy component. It creates it and decides how any downstream renderer may use it. * Move constants to shared Apparently we can't depend on react/src/ because the whole package is considered "external" as far as rollup is concerned.
1 parent 2fe0fbb commit fa03206

File tree

6 files changed

+95
-48
lines changed

6 files changed

+95
-48
lines changed

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

+3-7
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,16 @@
99

1010
import type {ThreadID} from './ReactThreadIDAllocator';
1111
import type {ReactElement} from 'shared/ReactElementType';
12-
import type {LazyComponent} from 'shared/ReactLazyComponent';
12+
import type {LazyComponent} from 'react/src/ReactLazy';
1313
import type {ReactProvider, ReactContext} from 'shared/ReactTypes';
1414

1515
import * as React from 'react';
1616
import invariant from 'shared/invariant';
1717
import getComponentName from 'shared/getComponentName';
1818
import describeComponentFrame from 'shared/describeComponentFrame';
1919
import ReactSharedInternals from 'shared/ReactSharedInternals';
20-
import {
21-
Resolved,
22-
Rejected,
23-
Pending,
24-
initializeLazyComponentType,
25-
} from 'shared/ReactLazyComponent';
20+
import {initializeLazyComponentType} from 'shared/ReactLazyComponent';
21+
import {Resolved, Rejected, Pending} from 'shared/ReactLazyStatusTags';
2622
import {
2723
warnAboutDeprecatedLifecycles,
2824
disableLegacyContext,

packages/react-reconciler/src/ReactFiberLazyComponent.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
* @flow
88
*/
99

10-
import type {LazyComponent} from 'shared/ReactLazyComponent';
10+
import type {LazyComponent} from 'react/src/ReactLazy';
1111

12-
import {Resolved, initializeLazyComponentType} from 'shared/ReactLazyComponent';
12+
import {Resolved} from 'shared/ReactLazyStatusTags';
13+
import {initializeLazyComponentType} from 'shared/ReactLazyComponent';
1314

1415
export function resolveDefaultProps(Component: any, baseProps: Object): Object {
1516
if (Component && Component.defaultProps) {

packages/react/src/ReactLazy.js

+44-6
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,61 @@
33
*
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
68
*/
79

8-
import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent';
9-
1010
import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
1111

12-
export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
13-
let lazyType = {
12+
type Thenable<T, R> = {
13+
then(resolve: (T) => mixed, reject: (mixed) => mixed): R,
14+
};
15+
16+
export type UninitializedLazyComponent<T> = {
17+
$$typeof: Symbol | number,
18+
_status: -1,
19+
_result: () => Thenable<{default: T, ...} | T, mixed>,
20+
};
21+
22+
export type PendingLazyComponent<T> = {
23+
$$typeof: Symbol | number,
24+
_status: 0,
25+
_result: Thenable<{default: T, ...} | T, mixed>,
26+
};
27+
28+
export type ResolvedLazyComponent<T> = {
29+
$$typeof: Symbol | number,
30+
_status: 1,
31+
_result: T,
32+
};
33+
34+
export type RejectedLazyComponent = {
35+
$$typeof: Symbol | number,
36+
_status: 2,
37+
_result: mixed,
38+
};
39+
40+
export type LazyComponent<T> =
41+
| UninitializedLazyComponent<T>
42+
| PendingLazyComponent<T>
43+
| ResolvedLazyComponent<T>
44+
| RejectedLazyComponent;
45+
46+
export function lazy<T>(
47+
ctor: () => Thenable<{default: T, ...} | T, mixed>,
48+
): LazyComponent<T> {
49+
let lazyType: LazyComponent<T> = {
1450
$$typeof: REACT_LAZY_TYPE,
15-
_ctor: ctor,
1651
// React uses these fields to store the result.
1752
_status: -1,
18-
_result: null,
53+
_result: ctor,
1954
};
2055

2156
if (__DEV__) {
2257
// In production, this would just set it on the object.
2358
let defaultProps;
2459
let propTypes;
60+
// $FlowFixMe
2561
Object.defineProperties(lazyType, {
2662
defaultProps: {
2763
configurable: true,
@@ -36,6 +72,7 @@ export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
3672
);
3773
defaultProps = newDefaultProps;
3874
// Match production behavior more closely:
75+
// $FlowFixMe
3976
Object.defineProperty(lazyType, 'defaultProps', {
4077
enumerable: true,
4178
});
@@ -54,6 +91,7 @@ export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
5491
);
5592
propTypes = newPropTypes;
5693
// Match production behavior more closely:
94+
// $FlowFixMe
5795
Object.defineProperty(lazyType, 'propTypes', {
5896
enumerable: true,
5997
});

packages/shared/ReactLazyComponent.js

+30-32
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,40 @@
77
* @flow
88
*/
99

10-
export type Thenable<T, R> = {
11-
then(resolve: (T) => mixed, reject: (mixed) => mixed): R,
12-
...
13-
};
10+
import type {
11+
PendingLazyComponent,
12+
ResolvedLazyComponent,
13+
RejectedLazyComponent,
14+
LazyComponent,
15+
} from 'react/src/ReactLazy';
1416

15-
export type LazyComponent<T> = {
16-
$$typeof: Symbol | number,
17-
_ctor: () => Thenable<{default: T, ...}, mixed>,
18-
_status: 0 | 1 | 2,
19-
_result: any,
20-
...
21-
};
22-
23-
type ResolvedLazyComponent<T> = {
24-
$$typeof: Symbol | number,
25-
_ctor: () => Thenable<{default: T, ...}, mixed>,
26-
_status: 1,
27-
_result: any,
28-
...
29-
};
30-
31-
export const Uninitialized = -1;
32-
export const Pending = 0;
33-
export const Resolved = 1;
34-
export const Rejected = 2;
17+
import {
18+
Uninitialized,
19+
Pending,
20+
Resolved,
21+
Rejected,
22+
} from './ReactLazyStatusTags';
3523

3624
export function refineResolvedLazyComponent<T>(
3725
lazyComponent: LazyComponent<T>,
38-
): ResolvedLazyComponent<T> | null {
26+
): T | null {
3927
return lazyComponent._status === Resolved ? lazyComponent._result : null;
4028
}
4129

4230
export function initializeLazyComponentType(
4331
lazyComponent: LazyComponent<any>,
4432
): void {
4533
if (lazyComponent._status === Uninitialized) {
46-
lazyComponent._status = Pending;
47-
const ctor = lazyComponent._ctor;
34+
let ctor = lazyComponent._result;
35+
if (!ctor) {
36+
// TODO: Remove this later. THis only exists in case you use an older "react" package.
37+
ctor = ((lazyComponent: any)._ctor: typeof ctor);
38+
}
4839
const thenable = ctor();
49-
lazyComponent._result = thenable;
40+
// Transition to the next state.
41+
const pending: PendingLazyComponent<any> = (lazyComponent: any);
42+
pending._status = Pending;
43+
pending._result = thenable;
5044
thenable.then(
5145
moduleObject => {
5246
if (lazyComponent._status === Pending) {
@@ -61,14 +55,18 @@ export function initializeLazyComponentType(
6155
);
6256
}
6357
}
64-
lazyComponent._status = Resolved;
65-
lazyComponent._result = defaultExport;
58+
// Transition to the next state.
59+
const resolved: ResolvedLazyComponent<any> = (lazyComponent: any);
60+
resolved._status = Resolved;
61+
resolved._result = defaultExport;
6662
}
6763
},
6864
error => {
6965
if (lazyComponent._status === Pending) {
70-
lazyComponent._status = Rejected;
71-
lazyComponent._result = error;
66+
// Transition to the next state.
67+
const rejected: RejectedLazyComponent = (lazyComponent: any);
68+
rejected._status = Rejected;
69+
rejected._result = error;
7270
}
7371
},
7472
);
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
// TODO: Move this to "react" once we can import from externals.
11+
export const Uninitialized = -1;
12+
export const Pending = 0;
13+
export const Resolved = 1;
14+
export const Rejected = 2;

packages/shared/getComponentName.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import type {LazyComponent} from 'shared/ReactLazyComponent';
10+
import type {LazyComponent} from 'react/src/ReactLazy';
1111

1212
import {
1313
REACT_CONTEXT_TYPE,

0 commit comments

Comments
 (0)