-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
Bug fix - SetState callback called before component state is updated in ReactShallowRenderer #11507
Changes from 2 commits
035eb3d
856cb2b
a269747
a13a3d6
11b931d
ae88abd
87bf19f
120b399
cfa6552
ffa5565
f242683
de20f22
194ff74
2141b8c
b3b0788
0a58682
ba0e995
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 |
---|---|---|
|
@@ -44,7 +44,7 @@ class ReactShallowRenderer { | |
'ReactShallowRenderer render(): Invalid component element.%s', | ||
typeof element === 'function' | ||
? ' Instead of passing a component class, make sure to instantiate ' + | ||
'it by passing it to React.createElement.' | ||
'it by passing it to React.createElement.' | ||
: '', | ||
); | ||
// Show a special message for host elements since it's a common case. | ||
|
@@ -139,6 +139,7 @@ class ReactShallowRenderer { | |
} | ||
|
||
this._rendered = this._instance.render(); | ||
this._updater._invokeCallback(); | ||
// Intentionally do not call componentDidMount() | ||
// because DOM refs are not available. | ||
} | ||
|
@@ -183,6 +184,7 @@ class ReactShallowRenderer { | |
|
||
if (shouldUpdate) { | ||
this._rendered = this._instance.render(); | ||
this._updater._invokeCallback(); | ||
} | ||
// Intentionally do not call componentDidUpdate() | ||
// because DOM refs are not available. | ||
|
@@ -192,31 +194,41 @@ class ReactShallowRenderer { | |
class Updater { | ||
constructor(renderer) { | ||
this._renderer = renderer; | ||
this._callback = null; | ||
this._publicInstance = null; | ||
} | ||
|
||
_updateCallback(callback, publicInstance) { | ||
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 _enqueueCallback |
||
if (typeof callback === 'function') { | ||
this._callback = callback; | ||
this._publicInstance = publicInstance; | ||
} | ||
} | ||
|
||
_invokeCallback() { | ||
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 |
||
if (typeof this._callback === 'function' && this._publicInstance) { | ||
this._callback.call(this._publicInstance); | ||
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. You'll probably want to immediately set it to null before calling. Since now it is outdated. |
||
} | ||
} | ||
|
||
isMounted(publicInstance) { | ||
return !!this._renderer._element; | ||
} | ||
|
||
enqueueForceUpdate(publicInstance, callback, callerName) { | ||
this._updateCallback(callback, publicInstance); | ||
this._renderer._forcedUpdate = true; | ||
this._renderer.render(this._renderer._element, this._renderer._context); | ||
|
||
if (typeof callback === 'function') { | ||
callback.call(publicInstance); | ||
} | ||
} | ||
|
||
enqueueReplaceState(publicInstance, completeState, callback, callerName) { | ||
this._updateCallback(callback, publicInstance); | ||
this._renderer._newState = completeState; | ||
this._renderer.render(this._renderer._element, this._renderer._context); | ||
|
||
if (typeof callback === 'function') { | ||
callback.call(publicInstance); | ||
} | ||
} | ||
|
||
enqueueSetState(publicInstance, partialState, callback, callerName) { | ||
this._updateCallback(callback, publicInstance); | ||
const currentState = this._renderer._newState || publicInstance.state; | ||
|
||
if (typeof partialState === 'function') { | ||
|
@@ -229,10 +241,6 @@ class Updater { | |
}; | ||
|
||
this._renderer.render(this._renderer._element, this._renderer._context); | ||
|
||
if (typeof callback === 'function') { | ||
callback.call(publicInstance); | ||
} | ||
} | ||
} | ||
|
||
|
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.
Does ReactDOM call the callback if
shouldComponentUpdate
skips an update? I would expect so, but this PR doesn't. Can you verify this?Maybe it's better to move the callback call here. Then you don't need to duplicate it in two branches.