-
Notifications
You must be signed in to change notification settings - Fork 47.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bailout broken in lazy components due to default props resolving #18491
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -997,11 +997,13 @@ function updateClassInstance( | |||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
cloneUpdateQueue(current, workInProgress); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const oldProps = workInProgress.memoizedProps; | ||||||||||||||||||||||||||||||||||||||||||||||||||
instance.props = | ||||||||||||||||||||||||||||||||||||||||||||||||||
const unresolvedOldProps = workInProgress.memoizedProps; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const oldProps = | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress.type === workInProgress.elementType | ||||||||||||||||||||||||||||||||||||||||||||||||||
? oldProps | ||||||||||||||||||||||||||||||||||||||||||||||||||
: resolveDefaultProps(workInProgress.type, oldProps); | ||||||||||||||||||||||||||||||||||||||||||||||||||
? unresolvedOldProps | ||||||||||||||||||||||||||||||||||||||||||||||||||
: resolveDefaultProps(workInProgress.type, unresolvedOldProps); | ||||||||||||||||||||||||||||||||||||||||||||||||||
instance.props = oldProps; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const unresolvedNewProps = workInProgress.pendingProps; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const oldContext = instance.context; | ||||||||||||||||||||||||||||||||||||||||||||||||||
const contextType = ctor.contextType; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1029,7 +1031,10 @@ function updateClassInstance( | |||||||||||||||||||||||||||||||||||||||||||||||||
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' || | ||||||||||||||||||||||||||||||||||||||||||||||||||
typeof instance.componentWillReceiveProps === 'function') | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (oldProps !== newProps || oldContext !== nextContext) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps !== unresolvedNewProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldContext !== nextContext | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
callComponentWillReceiveProps( | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress, | ||||||||||||||||||||||||||||||||||||||||||||||||||
instance, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1047,7 +1052,7 @@ function updateClassInstance( | |||||||||||||||||||||||||||||||||||||||||||||||||
newState = workInProgress.memoizedState; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldProps === newProps && | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps === unresolvedNewProps && | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldState === newState && | ||||||||||||||||||||||||||||||||||||||||||||||||||
!hasContextChanged() && | ||||||||||||||||||||||||||||||||||||||||||||||||||
!checkHasForceUpdateAfterProcessing() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1056,20 +1061,21 @@ function updateClassInstance( | |||||||||||||||||||||||||||||||||||||||||||||||||
// effect even though we're bailing out, so that cWU/cDU are called. | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof instance.componentDidUpdate === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldState !== current.memoizedState | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress.effectTag |= Update; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof instance.getSnapshotBeforeUpdate === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldState !== current.memoizedState | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress.effectTag |= Snapshot; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
instance.props = workInProgress.memoizedProps = newProps; | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise, React would warn. react/packages/react-reconciler/src/ReactFiberBeginWork.js Lines 859 to 868 in 1fd4543
This also mirrors the logic at the end of the same function. react/packages/react-reconciler/src/ReactFiberClassComponent.js Lines 1139 to 1151 in 1fd4543
This was not needed before because it was already guaranteed by the condition in the branch.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1121,15 +1127,15 @@ function updateClassInstance( | |||||||||||||||||||||||||||||||||||||||||||||||||
// effect even though we're bailing out, so that cWU/cDU are called. | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof instance.componentDidUpdate === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldState !== current.memoizedState | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress.effectTag |= Update; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (typeof instance.getSnapshotBeforeUpdate === 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
unresolvedOldProps !== current.memoizedProps || | ||||||||||||||||||||||||||||||||||||||||||||||||||
oldState !== current.memoizedState | ||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
workInProgress.effectTag |= Snapshot; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This says they're unresolved. But later we do this:
So next time we would have resolved props in
memoizedProps
? I don't quite follow the logic.Is there a way we could make it consistent? So that
memoizedProps
would always be unresolved, for example. Would that work?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we reset
workInProgress.memoizedProps
toworkInProgress.pendingProps
right after beginWork,workInProgress.memoizedProps
is always unresolved at the start of beginWork.react/packages/react-reconciler/src/ReactFiberWorkLoop.js
Line 1501 in e69ca31
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then can we assign
instance.props
only? Is there a reason forworkInPorgress.memoizedProps
assignment? Sorry I'm being dense, it's been a while since I looked a tthis.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind. But unfortunately we have to keep their values in sync. Here is the reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't think it makes sense to assign either of them.
In the sCU branch,
instance.props
reassignment makes sense because the passed props actually did change. We want the most recent values inside of them to be accessible to the lifecycle methods, even if sCU "lies" about them not having changed.In this branch, we've verified props are
===
. So the only reason they "changed" is because we resolved default props. That's not a compelling reason to give our components a different props object.As you noted,
memoizedProps
gets reset anyway. So it's confusing to assign it here if we know that's gonna happen.I think we should fix whatever causes the warning instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you change the warning condition to
if (shouldUpdate && inst.props !== nextProps) {
then the warning won't fire. It will also make sense because the render wasn't called — so the warning message would have been misleading anyway.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only gives our components a different props object when we've actually resolved default props. But in that case, components are already given a new props object.
react/packages/react-reconciler/src/ReactFiberClassComponent.js
Lines 1001 to 1004 in 2dddd1e
I think it's ok to remove this assignment if keeping
workInProgress.memoizedProps
andinstance.props
stay the same until beginWork finishes is not a requirement. And that seems true now. So let's change the warning condition instead.