Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion packages/react-reconciler/src/ReactChildFiber.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ import {
Block,
} from './ReactWorkTags';
import invariant from 'shared/invariant';
import {warnAboutStringRefs, enableBlocksAPI} from 'shared/ReactFeatureFlags';
import {
warnAboutStringRefs,
enableBlocksAPI,
enableLazyElements,
} from 'shared/ReactFeatureFlags';

import {
createWorkInProgress,
Expand Down Expand Up @@ -532,6 +536,13 @@ function ChildReconciler(shouldTrackSideEffects) {
created.return = returnFiber;
return created;
}
case REACT_LAZY_TYPE: {
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return createChild(returnFiber, init(payload), lanes);
}
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -602,6 +613,13 @@ function ChildReconciler(shouldTrackSideEffects) {
return null;
}
}
case REACT_LAZY_TYPE: {
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return updateSlot(returnFiber, oldFiber, init(payload), lanes);
}
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -663,6 +681,18 @@ function ChildReconciler(shouldTrackSideEffects) {
) || null;
return updatePortal(returnFiber, matchedFiber, newChild, lanes);
}
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return updateFromMap(
existingChildren,
returnFiber,
newIdx,
init(payload),
lanes,
);
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -720,6 +750,15 @@ function ChildReconciler(shouldTrackSideEffects) {
key,
);
break;
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = child._payload;
const init = (child._init: any);
warnOnInvalidKey(init(payload), knownKeys, returnFiber);
break;
}
// We intentionally fallthrough here if enableLazyElements is not on.
// eslint-disable-next-lined no-fallthrough
default:
break;
}
Expand Down Expand Up @@ -1276,6 +1315,18 @@ function ChildReconciler(shouldTrackSideEffects) {
lanes,
),
);
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
// TODO: This function is supposed to be non-recursive.
return reconcileChildFibers(
returnFiber,
currentFirstChild,
init(payload),
lanes,
);
}
}
}

Expand Down
58 changes: 57 additions & 1 deletion packages/react-reconciler/src/ReactChildFiber.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ import {
Block,
} from './ReactWorkTags';
import invariant from 'shared/invariant';
import {warnAboutStringRefs, enableBlocksAPI} from 'shared/ReactFeatureFlags';
import {
warnAboutStringRefs,
enableBlocksAPI,
enableLazyElements,
} from 'shared/ReactFeatureFlags';

import {
createWorkInProgress,
Expand Down Expand Up @@ -542,6 +546,13 @@ function ChildReconciler(shouldTrackSideEffects) {
created.return = returnFiber;
return created;
}
case REACT_LAZY_TYPE: {
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return createChild(returnFiber, init(payload), expirationTime);
}
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -627,6 +638,18 @@ function ChildReconciler(shouldTrackSideEffects) {
return null;
}
}
case REACT_LAZY_TYPE: {
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return updateSlot(
returnFiber,
oldFiber,
init(payload),
expirationTime,
);
}
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -709,6 +732,18 @@ function ChildReconciler(shouldTrackSideEffects) {
expirationTime,
);
}
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
return updateFromMap(
existingChildren,
returnFiber,
newIdx,
init(payload),
expirationTime,
);
}
}

if (isArray(newChild) || getIteratorFn(newChild)) {
Expand Down Expand Up @@ -772,6 +807,15 @@ function ChildReconciler(shouldTrackSideEffects) {
key,
);
break;
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = child._payload;
const init = (child._init: any);
warnOnInvalidKey(init(payload), knownKeys, returnFiber);
break;
}
// We intentionally fallthrough here if enableLazyElements is not on.
// eslint-disable-next-lined no-fallthrough
default:
break;
}
Expand Down Expand Up @@ -1349,6 +1393,18 @@ function ChildReconciler(shouldTrackSideEffects) {
expirationTime,
),
);
case REACT_LAZY_TYPE:
if (enableLazyElements) {
const payload = newChild._payload;
const init = newChild._init;
// TODO: This function is supposed to be non-recursive.
return reconcileChildFibers(
returnFiber,
currentFirstChild,
init(payload),
expirationTime,
);
}
}
}

Expand Down
76 changes: 76 additions & 0 deletions packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -1273,4 +1273,80 @@ describe('ReactLazy', () => {

expect(componentStackMessage).toContain('in Lazy');
});

// @gate enableLazyElements && enableNewReconciler
it('mount and reorder lazy elements', async () => {
class Child extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue('Did mount: ' + this.props.label);
}
componentDidUpdate() {
Scheduler.unstable_yieldValue('Did update: ' + this.props.label);
}
render() {
return <Text text={this.props.label} />;
}
}

const lazyChildA = lazy(() => {
Scheduler.unstable_yieldValue('Init A');
return fakeImport(<Child key="A" label="A" />);
});
const lazyChildB = lazy(() => {
Scheduler.unstable_yieldValue('Init B');
return fakeImport(<Child key="B" label="B" />);
});
const lazyChildA2 = lazy(() => {
Scheduler.unstable_yieldValue('Init A2');
return fakeImport(<Child key="A" label="a" />);
});
const lazyChildB2 = lazy(() => {
Scheduler.unstable_yieldValue('Init B2');
return fakeImport(<Child key="B" label="b" />);
});

function Parent({swap}) {
return (
<Suspense fallback={<Text text="Loading..." />}>
{swap ? [lazyChildB2, lazyChildA2] : [lazyChildA, lazyChildB]}
</Suspense>
);
}

const root = ReactTestRenderer.create(<Parent swap={false} />, {
unstable_isConcurrent: true,
});

expect(Scheduler).toFlushAndYield(['Init A', 'Loading...']);
expect(root).not.toMatchRenderedOutput('AB');

await lazyChildA;
// We need to flush to trigger the B to load.
expect(Scheduler).toFlushAndYield(['Init B']);
await lazyChildB;

expect(Scheduler).toFlushAndYield([
'A',
'B',
'Did mount: A',
'Did mount: B',
]);
expect(root).toMatchRenderedOutput('AB');

// Swap the position of A and B
root.update(<Parent swap={true} />);
expect(Scheduler).toFlushAndYield(['Init B2', 'Loading...']);
await lazyChildB2;
// We need to flush to trigger the second one to load.
expect(Scheduler).toFlushAndYield(['Init A2', 'Loading...']);
await lazyChildA2;

expect(Scheduler).toFlushAndYield([
'b',
'a',
'Did update: b',
'Did update: a',
]);
expect(root).toMatchRenderedOutput('ba');
});
});
1 change: 1 addition & 0 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const enableSelectiveHydration = __EXPERIMENTAL__;

// Flight experiments
export const enableBlocksAPI = __EXPERIMENTAL__;
export const enableLazyElements = __EXPERIMENTAL__;

// Only used in www builds.
export const enableSchedulerDebugging = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableBlocksAPI = false;
export const enableLazyElements = false;
export const enableSchedulerDebugging = false;
export const debugRenderPhaseSideEffectsForStrictMode = true;
export const disableJavaScriptURLs = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-oss.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableBlocksAPI = false;
export const enableLazyElements = false;
export const disableJavaScriptURLs = false;
export const disableInputAttributeSyncing = false;
export const enableSchedulerDebugging = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableBlocksAPI = false;
export const enableLazyElements = false;
export const disableJavaScriptURLs = false;
export const disableInputAttributeSyncing = false;
export const enableSchedulerDebugging = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableBlocksAPI = false;
export const enableLazyElements = false;
export const enableSchedulerDebugging = false;
export const disableJavaScriptURLs = false;
export const disableInputAttributeSyncing = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableBlocksAPI = false;
export const enableLazyElements = false;
export const disableJavaScriptURLs = false;
export const disableInputAttributeSyncing = false;
export const enableSchedulerDebugging = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const enableSchedulerTracing = false;
export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;
export const enableBlocksAPI = true;
export const enableLazyElements = false;
export const disableJavaScriptURLs = true;
export const disableInputAttributeSyncing = false;
export const enableSchedulerDebugging = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;

export const enableBlocksAPI = true;
export const enableLazyElements = true;

export const disableJavaScriptURLs = true;

Expand Down