Skip to content

Commit 4aad797

Browse files
committed
Add replayForwardRef
1 parent 58dd0f4 commit 4aad797

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,52 @@ function updateForwardRef(
465465
return workInProgress.child;
466466
}
467467

468+
export function replayForwardRef(
469+
current: Fiber | null,
470+
workInProgress: Fiber,
471+
nextProps: any,
472+
Component: any,
473+
renderLanes: Lanes,
474+
): Fiber | null {
475+
const secondArg = workInProgress.ref;
476+
477+
// This function is used to replay a component that previously suspended,
478+
// after its data resolves. It's a simplified version of
479+
// updateFunctionComponent that reuses the hooks from the previous attempt.
480+
481+
prepareToReadContext(workInProgress, renderLanes);
482+
if (enableSchedulingProfiler) {
483+
markComponentRenderStarted(workInProgress);
484+
}
485+
const nextChildren = replaySuspendedComponentWithHooks(
486+
current,
487+
workInProgress,
488+
Component,
489+
nextProps,
490+
secondArg,
491+
);
492+
493+
// the rest is a fork of updateFunctionComponent
494+
const hasId = checkDidRenderIdHook();
495+
if (enableSchedulingProfiler) {
496+
markComponentRenderStopped();
497+
}
498+
499+
if (current !== null && !didReceiveUpdate) {
500+
bailoutHooks(current, workInProgress, renderLanes);
501+
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
502+
}
503+
504+
if (getIsHydrating() && hasId) {
505+
pushMaterializedTreeId(workInProgress);
506+
}
507+
508+
// React DevTools reads this flag.
509+
workInProgress.flags |= PerformedWork;
510+
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
511+
return workInProgress.child;
512+
}
513+
468514
function updateMemoComponent(
469515
current: Fiber | null,
470516
workInProgress: Fiber,
@@ -1169,15 +1215,15 @@ export function replayFunctionComponent(
11691215
nextProps: any,
11701216
Component: any,
11711217
renderLanes: Lanes,
1172-
secondArg: any,
11731218
): Fiber | null {
11741219
// This function is used to replay a component that previously suspended,
11751220
// after its data resolves. It's a simplified version of
11761221
// updateFunctionComponent that reuses the hooks from the previous attempt.
11771222

1178-
if (!disableLegacyContext && secondArg === undefined) {
1223+
let context: any;
1224+
if (!disableLegacyContext) {
11791225
const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
1180-
secondArg = getMaskedContext(workInProgress, unmaskedContext);
1226+
context = getMaskedContext(workInProgress, unmaskedContext);
11811227
}
11821228

11831229
prepareToReadContext(workInProgress, renderLanes);
@@ -1189,7 +1235,7 @@ export function replayFunctionComponent(
11891235
workInProgress,
11901236
Component,
11911237
nextProps,
1192-
secondArg,
1238+
context,
11931239
);
11941240
const hasId = checkDidRenderIdHook();
11951241
if (enableSchedulingProfiler) {

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ import {
171171
SelectiveHydrationException,
172172
beginWork as originalBeginWork,
173173
replayFunctionComponent,
174+
replayForwardRef,
174175
} from './ReactFiberBeginWork';
175176
import {completeWork} from './ReactFiberCompleteWork';
176177
import {unwindWork, unwindInterruptedWork} from './ReactFiberUnwindWork';
@@ -2380,18 +2381,12 @@ function replaySuspendedUnitOfWork(unitOfWork: Fiber): void {
23802381
// Fallthrough to the next branch.
23812382
}
23822383
// eslint-disable-next-line no-fallthrough
2383-
case FunctionComponent:
2384-
case ForwardRef: {
2384+
case FunctionComponent: {
23852385
// Resolve `defaultProps`. This logic is copied from `beginWork`.
23862386
// TODO: Consider moving this switch statement into that module. Also,
23872387
// could maybe use this as an opportunity to say `use` doesn't work with
23882388
// `defaultProps` :)
2389-
const Component =
2390-
unitOfWork.tag === FunctionComponent
2391-
? unitOfWork.type
2392-
: unitOfWork.type.render;
2393-
const secondArg =
2394-
unitOfWork.tag === FunctionComponent ? undefined : unitOfWork.ref;
2389+
const Component = unitOfWork.type;
23952390
const unresolvedProps = unitOfWork.pendingProps;
23962391
const resolvedProps =
23972392
unitOfWork.elementType === Component
@@ -2403,21 +2398,38 @@ function replaySuspendedUnitOfWork(unitOfWork: Fiber): void {
24032398
resolvedProps,
24042399
Component,
24052400
workInProgressRootRenderLanes,
2406-
secondArg,
2401+
);
2402+
break;
2403+
}
2404+
case ForwardRef: {
2405+
// Resolve `defaultProps`. This logic is copied from `beginWork`.
2406+
// TODO: Consider moving this switch statement into that module. Also,
2407+
// could maybe use this as an opportunity to say `use` doesn't work with
2408+
// `defaultProps` :)
2409+
const Component = unitOfWork.type.render;
2410+
const unresolvedProps = unitOfWork.pendingProps;
2411+
const resolvedProps =
2412+
unitOfWork.elementType === Component
2413+
? unresolvedProps
2414+
: resolveDefaultProps(Component, unresolvedProps);
2415+
next = replayForwardRef(
2416+
current,
2417+
unitOfWork,
2418+
resolvedProps,
2419+
Component,
2420+
workInProgressRootRenderLanes,
24072421
);
24082422
break;
24092423
}
24102424
case SimpleMemoComponent: {
24112425
const Component = unitOfWork.type;
24122426
const nextProps = unitOfWork.pendingProps;
2413-
const secondArg = undefined;
24142427
next = replayFunctionComponent(
24152428
current,
24162429
unitOfWork,
24172430
nextProps,
24182431
Component,
24192432
workInProgressRootRenderLanes,
2420-
secondArg,
24212433
);
24222434
break;
24232435
}

0 commit comments

Comments
 (0)