diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js index af2ce6478ea90..1562dca186d4d 100644 --- a/packages/react-reconciler/src/ReactFiber.js +++ b/packages/react-reconciler/src/ReactFiber.js @@ -152,6 +152,7 @@ if (__DEV__) { function FiberNode( tag: TypeOfWork, + pendingProps: mixed, key: null | string, internalContextTag: TypeOfInternalContext, ) { @@ -169,7 +170,7 @@ function FiberNode( this.ref = null; - this.pendingProps = null; + this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; @@ -213,11 +214,12 @@ function FiberNode( // compatible. var createFiber = function( tag: TypeOfWork, + pendingProps: mixed, key: null | string, internalContextTag: TypeOfInternalContext, ): Fiber { // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, key, internalContextTag); + return new FiberNode(tag, pendingProps, key, internalContextTag); }; function shouldConstruct(Component) { @@ -239,6 +241,7 @@ export function createWorkInProgress( // reclaim the extra memory if needed. workInProgress = createFiber( current.tag, + pendingProps, current.key, current.internalContextTag, ); @@ -255,6 +258,8 @@ export function createWorkInProgress( workInProgress.alternate = current; current.alternate = workInProgress; } else { + workInProgress.pendingProps = pendingProps; + // We already have an alternate. // Reset the effect tag. workInProgress.effectTag = NoEffect; @@ -266,7 +271,6 @@ export function createWorkInProgress( } workInProgress.expirationTime = expirationTime; - workInProgress.pendingProps = pendingProps; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; @@ -297,17 +301,22 @@ export function createFiberFromElement( } let fiber; - const {type, key} = element; + const type = element.type; + const key = element.key; + const pendingProps = element.props; if (typeof type === 'function') { fiber = shouldConstruct(type) - ? createFiber(ClassComponent, key, internalContextTag) - : createFiber(IndeterminateComponent, key, internalContextTag); + ? createFiber(ClassComponent, pendingProps, key, internalContextTag) + : createFiber( + IndeterminateComponent, + pendingProps, + key, + internalContextTag, + ); fiber.type = type; - fiber.pendingProps = element.props; } else if (typeof type === 'string') { - fiber = createFiber(HostComponent, key, internalContextTag); + fiber = createFiber(HostComponent, pendingProps, key, internalContextTag); fiber.type = type; - fiber.pendingProps = element.props; } else if ( typeof type === 'object' && type !== null && @@ -320,7 +329,7 @@ export function createFiberFromElement( // we don't know if we can reuse that fiber or if we need to clone it. // There is probably a clever way to restructure this. fiber = ((type: any): Fiber); - fiber.pendingProps = element.props; + fiber.pendingProps = pendingProps; } else { let info = ''; if (__DEV__) { @@ -364,8 +373,7 @@ export function createFiberFromFragment( expirationTime: ExpirationTime, key: null | string, ): Fiber { - const fiber = createFiber(Fragment, key, internalContextTag); - fiber.pendingProps = elements; + const fiber = createFiber(Fragment, elements, key, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } @@ -375,14 +383,13 @@ export function createFiberFromText( internalContextTag: TypeOfInternalContext, expirationTime: ExpirationTime, ): Fiber { - const fiber = createFiber(HostText, null, internalContextTag); - fiber.pendingProps = content; + const fiber = createFiber(HostText, content, null, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } export function createFiberFromHostInstanceForDeletion(): Fiber { - const fiber = createFiber(HostComponent, null, NoContext); + const fiber = createFiber(HostComponent, null, null, NoContext); fiber.type = 'DELETED'; return fiber; } @@ -392,9 +399,8 @@ export function createFiberFromCall( internalContextTag: TypeOfInternalContext, expirationTime: ExpirationTime, ): Fiber { - const fiber = createFiber(CallComponent, call.key, internalContextTag); + const fiber = createFiber(CallComponent, call, call.key, internalContextTag); fiber.type = call.handler; - fiber.pendingProps = call; fiber.expirationTime = expirationTime; return fiber; } @@ -404,7 +410,7 @@ export function createFiberFromReturn( internalContextTag: TypeOfInternalContext, expirationTime: ExpirationTime, ): Fiber { - const fiber = createFiber(ReturnComponent, null, internalContextTag); + const fiber = createFiber(ReturnComponent, null, null, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } @@ -414,8 +420,13 @@ export function createFiberFromPortal( internalContextTag: TypeOfInternalContext, expirationTime: ExpirationTime, ): Fiber { - const fiber = createFiber(HostPortal, portal.key, internalContextTag); - fiber.pendingProps = portal.children || []; + const pendingProps = portal.children !== null ? portal.children : []; + const fiber = createFiber( + HostPortal, + pendingProps, + portal.key, + internalContextTag, + ); fiber.expirationTime = expirationTime; fiber.stateNode = { containerInfo: portal.containerInfo, diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index af748e3ca823d..59384d18fed19 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -141,13 +141,10 @@ export default function( } function updateFragment(current, workInProgress) { - var nextChildren = workInProgress.pendingProps; + const nextChildren = workInProgress.pendingProps; if (hasContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. - if (nextChildren === null) { - nextChildren = workInProgress.memoizedProps; - } } else if ( nextChildren === null || workInProgress.memoizedProps === nextChildren @@ -168,18 +165,14 @@ export default function( } function updateFunctionalComponent(current, workInProgress) { - var fn = workInProgress.type; - var nextProps = workInProgress.pendingProps; + const fn = workInProgress.type; + const nextProps = workInProgress.pendingProps; - const memoizedProps = workInProgress.memoizedProps; if (hasContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. - if (nextProps === null) { - nextProps = memoizedProps; - } } else { - if (nextProps === null || memoizedProps === nextProps) { + if (workInProgress.memoizedProps === nextProps) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } // TODO: consider bringing fn.shouldComponentUpdate() back. @@ -373,21 +366,13 @@ export default function( const type = workInProgress.type; const memoizedProps = workInProgress.memoizedProps; - let nextProps = workInProgress.pendingProps; - if (nextProps === null) { - nextProps = memoizedProps; - invariant( - nextProps !== null, - 'We should always have pending or current props. This error is ' + - 'likely caused by a bug in React. Please file an issue.', - ); - } + const nextProps = workInProgress.pendingProps; const prevProps = current !== null ? current.memoizedProps : null; if (hasContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. - } else if (nextProps === null || memoizedProps === nextProps) { + } else if (memoizedProps === nextProps) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } @@ -429,10 +414,7 @@ export default function( if (current === null) { tryToClaimNextHydratableInstance(workInProgress); } - let nextProps = workInProgress.pendingProps; - if (nextProps === null) { - nextProps = workInProgress.memoizedProps; - } + const nextProps = workInProgress.pendingProps; memoizeProps(workInProgress, nextProps); // Nothing to do here. This is terminal. We'll do the completion step // immediately after. @@ -534,19 +516,11 @@ export default function( } function updateCallComponent(current, workInProgress, renderExpirationTime) { - var nextCall = (workInProgress.pendingProps: null | ReactCall); + var nextCall = (workInProgress.pendingProps: ReactCall); if (hasContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. - if (nextCall === null) { - nextCall = current && current.memoizedProps; - invariant( - nextCall !== null, - 'We should always have pending or current props. This error is ' + - 'likely caused by a bug in React. Please file an issue.', - ); - } - } else if (nextCall === null || workInProgress.memoizedProps === nextCall) { + } else if (workInProgress.memoizedProps === nextCall) { nextCall = workInProgress.memoizedProps; // TODO: When bailing out, we might need to return the stateNode instead // of the child. To check it for work. @@ -585,22 +559,11 @@ export default function( renderExpirationTime, ) { pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - let nextChildren = workInProgress.pendingProps; + const nextChildren = workInProgress.pendingProps; if (hasContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. - if (nextChildren === null) { - nextChildren = current && current.memoizedProps; - invariant( - nextChildren != null, - 'We should always have pending or current props. This error is ' + - 'likely caused by a bug in React. Please file an issue.', - ); - } - } else if ( - nextChildren === null || - workInProgress.memoizedProps === nextChildren - ) { + } else if (workInProgress.memoizedProps === nextChildren) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 616599d1164a3..4bb475e409c25 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -433,14 +433,7 @@ export default function( const instance = workInProgress.stateNode; const state = instance.state || null; - - let props = workInProgress.pendingProps; - invariant( - props, - 'There must be pending props for an initial mount. This error is ' + - 'likely caused by a bug in React. Please file an issue.', - ); - + const props = workInProgress.pendingProps; const unmaskedContext = getUnmaskedContext(workInProgress); instance.props = props; @@ -593,17 +586,7 @@ export default function( resetInputPointers(workInProgress, instance); const oldProps = workInProgress.memoizedProps; - let newProps = workInProgress.pendingProps; - if (!newProps) { - // If there aren't any new props, then we'll reuse the memoized props. - // This could be from already completed work. - newProps = oldProps; - invariant( - newProps != null, - 'There should always be pending or memoized props. This error is ' + - 'likely caused by a bug in React. Please file an issue.', - ); - } + const newProps = workInProgress.pendingProps; const oldContext = instance.context; const newUnmaskedContext = getUnmaskedContext(workInProgress); const newContext = getMaskedContext(workInProgress, newUnmaskedContext); diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index 8c83bd476f43c..d918f769dc38d 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -41,7 +41,6 @@ import { popContextProvider, popTopLevelContextObject, } from './ReactFiberContext'; -import {Never} from './ReactFiberExpirationTime'; export default function( config: HostConfig, @@ -392,18 +391,7 @@ export default function( workInProgress: Fiber, renderExpirationTime: ExpirationTime, ): Fiber | null { - // Get the latest props. - let newProps = workInProgress.pendingProps; - if (newProps === null) { - newProps = workInProgress.memoizedProps; - } else if ( - workInProgress.expirationTime !== Never || - renderExpirationTime === Never - ) { - // Reset the pending props, unless this was a down-prioritization. - workInProgress.pendingProps = null; - } - + const newProps = workInProgress.pendingProps; switch (workInProgress.tag) { case FunctionalComponent: return null;