From 30ca893db9652fc77aeb15b439978997198df02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=83=E5=BD=A6?= Date: Thu, 26 Sep 2019 20:08:24 +0800 Subject: [PATCH 1/2] fix: componentDidMount exec correct --- packages/rax/src/vdom/composite.js | 24 ++++++++++++++---------- packages/rax/src/vdom/native.js | 16 +++++++++++----- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/packages/rax/src/vdom/composite.js b/packages/rax/src/vdom/composite.js index 5e5a4e1ecb..b763e50395 100644 --- a/packages/rax/src/vdom/composite.js +++ b/packages/rax/src/vdom/composite.js @@ -59,7 +59,7 @@ if (process.env.NODE_ENV !== 'production') { * Composite Component */ class CompositeComponent extends BaseComponent { - __mountComponent(parent, parentInstance, context, nativeNodeMounter) { + __mountComponent(parent, parentInstance, context, nativeNodeMounter, didMountWorks) { this.__initComponent(parent, parentInstance, context); if (process.env.NODE_ENV !== 'production') { @@ -156,7 +156,8 @@ class CompositeComponent extends BaseComponent { this._parent, instance, this.__processChildContext(context), - nativeNodeMounter + nativeNodeMounter, + didMountWorks ); if (error) { @@ -168,15 +169,18 @@ class CompositeComponent extends BaseComponent { } if (instance.componentDidMount) { - performInSandbox(() => { - if (process.env.NODE_ENV !== 'production') { - measureLifeCycle(() => { + const didMount = () => { + performInSandbox(() => { + if (process.env.NODE_ENV !== 'production') { + measureLifeCycle(() => { + instance.componentDidMount(); + }, this._mountID, 'componentDidMount'); + } else { instance.componentDidMount(); - }, this._mountID, 'componentDidMount'); - } else { - instance.componentDidMount(); - } - }, instance); + } + }, instance); + }; + didMountWorks ? didMountWorks.push(didMount) : didMount(); } // Trigger setState callback in componentWillMount or boundary callback after rendered diff --git a/packages/rax/src/vdom/native.js b/packages/rax/src/vdom/native.js index 2b97bc9b1a..c47a7235c1 100644 --- a/packages/rax/src/vdom/native.js +++ b/packages/rax/src/vdom/native.js @@ -42,8 +42,13 @@ export default class NativeComponent extends BaseComponent { if (appendType === TREE) { // Should after process children when mount by tree mode - this.__mountChildren(children, context); + const didMountWorks = []; + this.__mountChildren(children, context, didMountWorks); this.__mountNativeNode(nativeNodeMounter); + let work; + while (work = didMountWorks.pop()) { + work(); + } } else { // Should before process children when mount by node mode this.__mountNativeNode(nativeNodeMounter); @@ -62,14 +67,14 @@ export default class NativeComponent extends BaseComponent { return instance; } - __mountChildren(children, context) { + __mountChildren(children, context, didMountWorks) { if (children == null) return children; const nativeNode = this.__getNativeNode(); - return this.__mountChildrenImpl(nativeNode, toArray(children), context); + return this.__mountChildrenImpl(nativeNode, toArray(children), context, null, didMountWorks); } - __mountChildrenImpl(parent, children, context, nativeNodeMounter) { + __mountChildrenImpl(parent, children, context, nativeNodeMounter, didMountWorks) { let renderedChildren = this.__renderedChildren = {}; const renderedChildrenImage = []; @@ -84,7 +89,8 @@ export default class NativeComponent extends BaseComponent { parent, this[INSTANCE], context, - nativeNodeMounter + nativeNodeMounter, + didMountWorks ); renderedChildrenImage.push(mountImage); } From 96fc7e5f5a52dfc65690afd1803990a49b2980d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=83=E5=BD=A6?= Date: Fri, 27 Sep 2019 21:36:36 +0800 Subject: [PATCH 2/2] fix: didMount works correct in fragment --- packages/rax/src/vdom/__tests__/composite.js | 48 +++++++++++++++++++- packages/rax/src/vdom/fragment.js | 12 +++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/packages/rax/src/vdom/__tests__/composite.js b/packages/rax/src/vdom/__tests__/composite.js index 90bd8827c5..bf212c8f96 100644 --- a/packages/rax/src/vdom/__tests__/composite.js +++ b/packages/rax/src/vdom/__tests__/composite.js @@ -494,13 +494,13 @@ describe('CompositeComponent', function() { expect(logs).toEqual([ 'componentWillMount1', 'render1', - 'componentDidMount1', 'componentWillMount2', 'render2', - 'componentDidMount2', 'componentWillMount3', 'render3', 'componentDidMount3', + 'componentDidMount2', + 'componentDidMount1', 'componentDidMountErrorBoundary', 'componentWillUnmount1', 'componentWillUnmount2', @@ -533,6 +533,50 @@ describe('CompositeComponent', function() { expect(container.childNodes[0].tagName).toBe('DIV'); }); + it('render component that componentDidMount could get mounted DOM', () => { + let container = createNodeElement('div'); + class Child extends Component { + componentDidMount() { + expect(container.childNodes[0].tagName).toBe('DIV'); + } + render() { + return
; + } + } + class App extends Component { + render() { + return ; + } + } + + const instance = render(, container); + jest.runAllTimers(); + expect(container.childNodes[0].tagName).toBe('DIV'); + }); + + it('render with fragment that componentDidMount could get mounted DOM', () => { + let container = createNodeElement('div'); + class Child extends Component { + componentDidMount() { + expect(container.childNodes[0].tagName).toBe('DIV'); + } + render() { + return
; + } + } + class App extends Component { + render() { + return [ + + ]; + } + } + + const instance = render(, container); + jest.runAllTimers(); + expect(container.childNodes[0].tagName).toBe('DIV'); + }); + it('schedules sync updates when inside componentDidMount/Update', () => { let container = createNodeElement('div'); let instance; diff --git a/packages/rax/src/vdom/fragment.js b/packages/rax/src/vdom/fragment.js index a244444dc2..79f2855d73 100644 --- a/packages/rax/src/vdom/fragment.js +++ b/packages/rax/src/vdom/fragment.js @@ -15,7 +15,8 @@ class FragmentComponent extends NativeComponent { instance[INTERNAL] = this; // Mount children - this.__mountChildren(this.__currentElement, context); + const didMountWorks = []; + this.__mountChildren(this.__currentElement, context, didMountWorks); let fragment = this.__getNativeNode(); @@ -27,6 +28,11 @@ class FragmentComponent extends NativeComponent { } } + let work; + while (work = didMountWorks.pop()) { + work(); + } + if (process.env.NODE_ENV !== 'production') { this.__currentElement.type = FragmentComponent; Host.reconciler.mountComponent(this); @@ -35,7 +41,7 @@ class FragmentComponent extends NativeComponent { return instance; } - __mountChildren(children, context) { + __mountChildren(children, context, didMountWorks) { let fragment = this.__getNativeNode(); return this.__mountChildrenImpl(this._parent, children, context, (nativeNode) => { @@ -43,7 +49,7 @@ class FragmentComponent extends NativeComponent { for (let i = 0; i < nativeNode.length; i++) { fragment.push(nativeNode[i]); } - }); + }, didMountWorks); } unmountComponent(shouldNotRemoveChild) {