-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Disable console.logs in the second render pass of DEV mode double render #18547
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 |
---|---|---|
|
@@ -181,6 +181,8 @@ import { | |
getWorkInProgressRoot, | ||
} from './ReactFiberWorkLoop'; | ||
|
||
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; | ||
|
||
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; | ||
|
||
let didReceiveUpdate: boolean = false; | ||
|
@@ -320,14 +322,19 @@ function updateForwardRef( | |
debugRenderPhaseSideEffectsForStrictMode && | ||
workInProgress.mode & StrictMode | ||
) { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
render, | ||
nextProps, | ||
ref, | ||
renderExpirationTime, | ||
); | ||
disableLogs(); | ||
try { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
render, | ||
nextProps, | ||
ref, | ||
renderExpirationTime, | ||
); | ||
} finally { | ||
reenableLogs(); | ||
} | ||
} | ||
setIsRendering(false); | ||
} else { | ||
|
@@ -658,14 +665,19 @@ function updateFunctionComponent( | |
debugRenderPhaseSideEffectsForStrictMode && | ||
workInProgress.mode & StrictMode | ||
) { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
Component, | ||
nextProps, | ||
context, | ||
renderExpirationTime, | ||
); | ||
disableLogs(); | ||
try { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
Component, | ||
nextProps, | ||
context, | ||
renderExpirationTime, | ||
); | ||
} finally { | ||
reenableLogs(); | ||
} | ||
} | ||
setIsRendering(false); | ||
} else { | ||
|
@@ -731,14 +743,19 @@ function updateBlock<Props, Data>( | |
debugRenderPhaseSideEffectsForStrictMode && | ||
workInProgress.mode & StrictMode | ||
) { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
render, | ||
nextProps, | ||
data, | ||
renderExpirationTime, | ||
); | ||
disableLogs(); | ||
try { | ||
nextChildren = renderWithHooks( | ||
current, | ||
workInProgress, | ||
render, | ||
nextProps, | ||
data, | ||
renderExpirationTime, | ||
); | ||
} finally { | ||
reenableLogs(); | ||
} | ||
} | ||
setIsRendering(false); | ||
} else { | ||
|
@@ -923,7 +940,12 @@ function finishClassComponent( | |
debugRenderPhaseSideEffectsForStrictMode && | ||
workInProgress.mode & StrictMode | ||
) { | ||
instance.render(); | ||
disableLogs(); | ||
try { | ||
instance.render(); | ||
} finally { | ||
reenableLogs(); | ||
} | ||
} | ||
setIsRendering(false); | ||
} else { | ||
|
@@ -1485,14 +1507,19 @@ function mountIndeterminateComponent( | |
debugRenderPhaseSideEffectsForStrictMode && | ||
workInProgress.mode & StrictMode | ||
) { | ||
value = renderWithHooks( | ||
null, | ||
workInProgress, | ||
Component, | ||
props, | ||
context, | ||
renderExpirationTime, | ||
); | ||
disableLogs(); | ||
try { | ||
value = renderWithHooks( | ||
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. I could foresee some confusion if the logs don't correspond to the value that is returned. It usually doesn't matter because it's supposed to be pure, but in the case where it's not, you might use 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. So I was actually surprised that we used the second value. I was thinking we should ignore the second value like we do for class constructors. 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. In my other PR's replaying I have to ignore it because I force an error inside the function. Similarly the react-debug-tools for Hooks debugging it's just replayed stand-alone. Doesn't necessarily mean we have to do the same here. I guess that's how I look at these. 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. It's intentional because the children are bound to the work-in-progress fiber via the It was a very confusing bug when we found it :D 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. This one: #14698 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. I could go either way on if the second render should process the update queue and even leave any side-effects. :) 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. Maybe the second render should have a different dispatcher that warns if you call setState again since you shouldn't call setState again for the same input. 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.
It can work but it needs to include internal mutations/side-effects too. We'd have to make it so that 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.
Oh I didn't see that. Yeah I think that would work. Just call the component again with a special dispatcher that doesn't mutate anything. 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.
I might be misunderstanding this comment, but if the second call has state updates already applied, then we might miss out on triggering the observable side effects in the first place (e.g. like something that happens only when props/state meet a certain criteria). |
||
null, | ||
workInProgress, | ||
Component, | ||
props, | ||
context, | ||
renderExpirationTime, | ||
); | ||
} finally { | ||
reenableLogs(); | ||
} | ||
} | ||
} | ||
reconcileChildren(null, workInProgress, value, renderExpirationTime); | ||
|
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.
Can remove
internal
suffix nowThere 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.
Yea I'll do a follow up to rename all these if I land this. I think the remaining ones are just using the
let ops = []
pattern and we can port those.