-
Notifications
You must be signed in to change notification settings - Fork 46.8k
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
[Fiber] Add top level render callbacks into ReactDOMFiber and ReactNoop #8102
Changes from 1 commit
465047a
3f50ce6
8581a92
b377c79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -308,6 +308,14 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) { | |
attachRef(current, finishedWork, instance); | ||
return; | ||
} | ||
case HostContainer: { | ||
const instance = finishedWork.stateNode; | ||
if (instance.callbackList) { | ||
const { callbackList } = instance; | ||
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. Style nit: const {callbackList} = instance; 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. @gaearon spaces inside curly braces aren't needed? Is there a rule for that? |
||
instance.callbackList = null; | ||
callCallbacks(callbackList, instance); | ||
} | ||
} | ||
case HostComponent: { | ||
const instance : I = finishedWork.stateNode; | ||
attachRef(current, finishedWork, instance); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,6 +165,11 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) { | |
const current = finishedWork.alternate; | ||
commitWork(current, finishedWork); | ||
} | ||
// if the root is a HostContainer, it may have a callback. | ||
if (finishedWork.tag === HostContainer) { | ||
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 tag will be checked inside of commitLifeCycles so there is no need to do it here. You can just remove the conditional. 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. ok, I've fixed it! |
||
const current = finishedWork.alternate; | ||
commitLifeCycles(current, finishedWork); | ||
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 needs to move in behind the effectTag check. Because we don't want to invoke this unless the root updates. This can happen if a render is scheduled, but we do a deep setState update at a higher priority first. This isn't actually possible right now without #7457 but it will be. 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've moved it to behind the effectTag check. |
||
} | ||
} | ||
|
||
function resetWorkPriority(workInProgress : Fiber) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ describe('ReactIncremental', () => { | |
|
||
it('should render a simple component, in steps if needed', () => { | ||
|
||
var renderCallbackCalled = false; | ||
var barCalled = false; | ||
function Bar() { | ||
barCalled = true; | ||
|
@@ -52,17 +53,20 @@ describe('ReactIncremental', () => { | |
]; | ||
} | ||
|
||
ReactNoop.render(<Foo />); | ||
ReactNoop.render(<Foo />, () => renderCallbackCalled = true); | ||
expect(fooCalled).toBe(false); | ||
expect(barCalled).toBe(false); | ||
expect(renderCallbackCalled).toBe(false); | ||
// Do one step of work. | ||
ReactNoop.flushDeferredPri(7 + 5); | ||
expect(fooCalled).toBe(true); | ||
expect(barCalled).toBe(false); | ||
expect(renderCallbackCalled).toBe(false); | ||
// Do the rest of the work. | ||
ReactNoop.flushDeferredPri(50); | ||
expect(fooCalled).toBe(true); | ||
expect(barCalled).toBe(true); | ||
expect(renderCallbackCalled).toBe(true); | ||
}); | ||
|
||
it('updates a previous render', () => { | ||
|
@@ -98,21 +102,21 @@ describe('ReactIncremental', () => { | |
); | ||
} | ||
|
||
ReactNoop.render(<Foo text="foo" />); | ||
ReactNoop.render(<Foo text="foo" />, () => ops.push('renderCallbackCalled')); | ||
ReactNoop.flush(); | ||
|
||
expect(ops).toEqual(['Foo', 'Header', 'Content', 'Footer']); | ||
expect(ops).toEqual(['Foo', 'Header', 'Content', 'Footer', 'renderCallbackCalled']); | ||
|
||
ops = []; | ||
|
||
ReactNoop.render(<Foo text="bar" />); | ||
ReactNoop.render(<Foo text="bar" />, () => ops.push('renderCallbackCalled')); | ||
ReactNoop.flush(); | ||
|
||
// TODO: Test bail out of host components. This is currently unobservable. | ||
|
||
// Since this is an update, it should bail out and reuse the work from | ||
// Header and Content. | ||
expect(ops).toEqual(['Foo', 'Content']); | ||
expect(ops).toEqual(['Foo', 'Content', 'renderCallbackCalled']); | ||
|
||
}); | ||
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. Should we also have a test verifying that if you queue two callbacks without flushing, and then flush once, both get called? 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 this case, I think two callbacks should be called after flushing. I've added a test for it. |
||
|
||
|
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 noticed the stack reconciler also passed the public instance as
this
into the callback.I found it weird but I guess we should do it here as well for feature parity.
See the test verifying it (it will fail due to missing
unstable_batchedUpdates
but you can temporarily comment it to check if a future fix works).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.
@gaearon Thanks! I've fixed that
this
in render callbacks is the public instance.Then I confirmed the tests linked from your comment are passed when
unstable_batchedUpdates
is mocked.I'll fix it after this PR was merged.