-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Improve error message when mutable sources are mutated during render #20665
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 |
---|---|---|
|
@@ -904,6 +904,18 @@ function readFromUnsubcribedMutableSource<Source, Snapshot>( | |
const getVersion = source._getVersion; | ||
const version = getVersion(source._source); | ||
|
||
let mutableSourceSideEffectDetected = false; | ||
if (__DEV__) { | ||
// Detect side effects that update a mutable source during render. | ||
// See https://github.com/facebook/react/issues/19948 | ||
if (source._currentlyRenderingFiber !== currentlyRenderingFiber) { | ||
source._currentlyRenderingFiber = currentlyRenderingFiber; | ||
source._initialVersionAsOfFirstRender = version; | ||
Comment on lines
+911
to
+913
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 will cause us to over-retain Fibers a little DEV mode. I assume that's not a problem but if it was I could add explicit cleanup somewhere. |
||
} else if (source._initialVersionAsOfFirstRender !== version) { | ||
mutableSourceSideEffectDetected = true; | ||
} | ||
} | ||
|
||
// Is it safe for this component to read from this source during the current render? | ||
let isSafeToReadFromSource = false; | ||
|
||
|
@@ -966,9 +978,20 @@ function readFromUnsubcribedMutableSource<Source, Snapshot>( | |
// but there's nothing we can do about that (short of throwing here and refusing to continue the render). | ||
markSourceAsDirty(source); | ||
|
||
if (__DEV__) { | ||
if (mutableSourceSideEffectDetected) { | ||
const componentName = getComponentName(currentlyRenderingFiber.type); | ||
console.warn( | ||
'A mutable source was mutated while the %s component was rendering. This is not supported. ' + | ||
'Move any mutations into event handlers or effects.', | ||
componentName, | ||
); | ||
} | ||
} | ||
|
||
invariant( | ||
false, | ||
'Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue.', | ||
'Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue.', | ||
); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -885,6 +885,18 @@ function readFromUnsubcribedMutableSource<Source, Snapshot>( | |
const getVersion = source._getVersion; | ||
const version = getVersion(source._source); | ||
|
||
let mutableSourceSideEffectDetected = false; | ||
if (__DEV__) { | ||
// Detect side effects that update a mutable source during render. | ||
// See https://github.com/facebook/react/issues/19948 | ||
if (source._currentlyRenderingFiber !== currentlyRenderingFiber) { | ||
source._currentlyRenderingFiber = currentlyRenderingFiber; | ||
source._initialVersionAsOfFirstRender = version; | ||
} else if (source._initialVersionAsOfFirstRender !== version) { | ||
mutableSourceSideEffectDetected = true; | ||
} | ||
} | ||
|
||
// Is it safe for this component to read from this source during the current render? | ||
let isSafeToReadFromSource = false; | ||
|
||
|
@@ -947,9 +959,20 @@ function readFromUnsubcribedMutableSource<Source, Snapshot>( | |
// but there's nothing we can do about that (short of throwing here and refusing to continue the render). | ||
markSourceAsDirty(source); | ||
|
||
if (__DEV__) { | ||
if (mutableSourceSideEffectDetected) { | ||
const componentName = getComponentName(currentlyRenderingFiber.type); | ||
console.warn( | ||
'A mutable source was mutated while the %s component was rendering. This is not supported. ' + | ||
'Move any mutations into event handlers or effects.', | ||
componentName, | ||
); | ||
} | ||
} | ||
|
||
invariant( | ||
false, | ||
'Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue.', | ||
'Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue.', | ||
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. Problem solved 😎 |
||
); | ||
} | ||
} | ||
|
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.
How does this account for multiple components that read from the same source?
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.
Nvm I get it now