( current: Fiber | null, workInProgress: Fiber, Component: any, nextProps: any, renderLanes: Lanes, )
| 404 | } |
| 405 | |
| 406 | function updateForwardRef( |
| 407 | current: Fiber | null, |
| 408 | workInProgress: Fiber, |
| 409 | Component: any, |
| 410 | nextProps: any, |
| 411 | renderLanes: Lanes, |
| 412 | ) { |
| 413 | // TODO: current can be non-null here even if the component |
| 414 | // hasn't yet mounted. This happens after the first render suspends. |
| 415 | // We'll need to figure out if this is fine or can cause issues. |
| 416 | const render = Component.render; |
| 417 | const ref = workInProgress.ref; |
| 418 | |
| 419 | let propsWithoutRef; |
| 420 | if ('ref' in nextProps) { |
| 421 | // `ref` is just a prop now, but `forwardRef` expects it to not appear in |
| 422 | // the props object. This used to happen in the JSX runtime, but now we do |
| 423 | // it here. |
| 424 | propsWithoutRef = ({}: {[string]: any}); |
| 425 | for (const key in nextProps) { |
| 426 | // Since `ref` should only appear in props via the JSX transform, we can |
| 427 | // assume that this is a plain object. So we don't need a |
| 428 | // hasOwnProperty check. |
| 429 | if (key !== 'ref') { |
| 430 | propsWithoutRef[key] = nextProps[key]; |
| 431 | } |
| 432 | } |
| 433 | } else { |
| 434 | propsWithoutRef = nextProps; |
| 435 | } |
| 436 | |
| 437 | // The rest is a fork of updateFunctionComponent |
| 438 | prepareToReadContext(workInProgress, renderLanes); |
| 439 | if (enableSchedulingProfiler) { |
| 440 | markComponentRenderStarted(workInProgress); |
| 441 | } |
| 442 | |
| 443 | const nextChildren = renderWithHooks( |
| 444 | current, |
| 445 | workInProgress, |
| 446 | render, |
| 447 | propsWithoutRef, |
| 448 | ref, |
| 449 | renderLanes, |
| 450 | ); |
| 451 | const hasId = checkDidRenderIdHook(); |
| 452 | |
| 453 | if (enableSchedulingProfiler) { |
| 454 | markComponentRenderStopped(); |
| 455 | } |
| 456 | |
| 457 | if (current !== null && !didReceiveUpdate) { |
| 458 | bailoutHooks(current, workInProgress, renderLanes); |
| 459 | return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); |
| 460 | } |
| 461 | |
| 462 | if (getIsHydrating() && hasId) { |
| 463 | pushMaterializedTreeId(workInProgress); |
no test coverage detected