From fe8155a2fc56c7cedce5dc5607ee4ba784a4361b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=96=8C?= Date: Sun, 22 Mar 2020 21:14:05 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20getContainer=E6=94=B9=E5=8F=98?= =?UTF-8?q?=E5=90=8E=E6=9B=B4=E6=96=B0Portal=E7=9A=84=E5=AE=B9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/Portal.js | 20 ++++++++++++++------ tests/container.test.js | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 tests/container.test.js diff --git a/package.json b/package.json index e564828b..79ee33e3 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "create-react-class": "^15.6.3", "enzyme": "^3.10.0", "eslint": "^6.6.0", + "eslint-plugin-react-hooks": "^2.5.1", "father": "^2.14.0", "np": "^5.0.3", "react": "^16.2.0", diff --git a/src/Portal.js b/src/Portal.js index 58babf85..cc18e753 100644 --- a/src/Portal.js +++ b/src/Portal.js @@ -7,7 +7,11 @@ export default class Portal extends React.Component { getContainer: PropTypes.func.isRequired, children: PropTypes.node.isRequired, didUpdate: PropTypes.func, - } + }; + + static defaultProps = { + didUpdate: ()=> void, + }; componentDidMount() { this.createContainer(); @@ -25,19 +29,23 @@ export default class Portal extends React.Component { } createContainer() { - this._container = this.props.getContainer(); + this.portalContainer = this.props.getContainer(); this.forceUpdate(); } removeContainer() { - if (this._container) { - this._container.parentNode.removeChild(this._container); + if (this.portalContainer) { + this.portalContainer = null; } } render() { - if (this._container) { - return ReactDOM.createPortal(this.props.children, this._container); + if (this.portalContainer) { + const currentContainer = this.props.getContainer(); + if (currentContainer && this.portalContainer !== currentContainer) { + this.portalContainer = currentContainer; + } + return ReactDOM.createPortal(this.props.children, this.portalContainer); } return null; } diff --git a/tests/container.test.js b/tests/container.test.js new file mode 100644 index 00000000..ba8504b1 --- /dev/null +++ b/tests/container.test.js @@ -0,0 +1,39 @@ +// import React from 'react'; +// import { mount } from 'enzyme'; +// import PortalWrapper from '../src/PortalWrapper'; + +// const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout)); + +// describe('container', () => { +// it('Same function returns different DOM', async () => { +// let root = document.getElementById('root'); +// if (!root) { +// root = document.createElement('div', { id: 'root' }); +// root.id = 'root'; +// document.body.appendChild(root); +// } +// mount( +//
+//
Hello
+//
World
+//
, +// { attachTo: root }, +// ); +// const holdContainer = { +// container: document.getElementById('dom1'), +// }; +// const getContainer = () => { +// return holdContainer.container; +// }; +// const wrapper = mount( +// +// {() => 'Content'} +// , +// ); +// expect(wrapper).toMatchSnapshot(); +// await delay(1000); +// holdContainer.container = document.getElementById('dom2'); +// wrapper.setProps({ 'data-only-trigger-re-render': true }); +// expect(wrapper).toMatchSnapshot(); +// }); +// }); From 6abdcb54351cd292a92139513185c9d4037ac905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=96=8C?= Date: Sun, 22 Mar 2020 22:09:33 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B=E5=92=8C=E8=A7=A3=E5=86=B3ci?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Portal.js | 2 +- tests/container.test.js | 72 ++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/Portal.js b/src/Portal.js index cc18e753..78c50ee6 100644 --- a/src/Portal.js +++ b/src/Portal.js @@ -10,7 +10,7 @@ export default class Portal extends React.Component { }; static defaultProps = { - didUpdate: ()=> void, + didUpdate: false, }; componentDidMount() { diff --git a/tests/container.test.js b/tests/container.test.js index ba8504b1..a8042491 100644 --- a/tests/container.test.js +++ b/tests/container.test.js @@ -1,39 +1,37 @@ -// import React from 'react'; -// import { mount } from 'enzyme'; -// import PortalWrapper from '../src/PortalWrapper'; +import React from 'react'; +import { mount } from 'enzyme'; +import PortalWrapper from '../src/PortalWrapper'; -// const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout)); +const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout)); -// describe('container', () => { -// it('Same function returns different DOM', async () => { -// let root = document.getElementById('root'); -// if (!root) { -// root = document.createElement('div', { id: 'root' }); -// root.id = 'root'; -// document.body.appendChild(root); -// } -// mount( -//
-//
Hello
-//
World
-//
, -// { attachTo: root }, -// ); -// const holdContainer = { -// container: document.getElementById('dom1'), -// }; -// const getContainer = () => { -// return holdContainer.container; -// }; -// const wrapper = mount( -// -// {() => 'Content'} -// , -// ); -// expect(wrapper).toMatchSnapshot(); -// await delay(1000); -// holdContainer.container = document.getElementById('dom2'); -// wrapper.setProps({ 'data-only-trigger-re-render': true }); -// expect(wrapper).toMatchSnapshot(); -// }); -// }); +describe('container', () => { + it('Same function returns different DOM', async () => { + let root = document.getElementById('root'); + if (!root) { + root = document.createElement('div', { id: 'root' }); + root.id = 'root'; + document.body.appendChild(root); + } + mount( +
+
Hello
+
World
+
, + { attachTo: root }, + ); + const holdContainer = { + container: document.getElementById('dom1'), + }; + const getContainer = () => holdContainer.container; + const wrapper = mount( + + {() => 'Content'} + , + ); + expect(wrapper).toMatchSnapshot(); + await delay(1000); + holdContainer.container = document.getElementById('dom2'); + wrapper.setProps({ 'data-only-trigger-re-render': true }); + expect(wrapper).toMatchSnapshot(); + }); +}); From ba941f36570ee52d05586dab1f89fac19ed86e24 Mon Sep 17 00:00:00 2001 From: binyellow <571704908@qq.com> Date: Tue, 24 Mar 2020 15:05:27 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9container?= =?UTF-8?q?=E5=91=BD=E5=90=8D=EF=BC=8CrmoveContainer=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Portal.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Portal.js b/src/Portal.js index 78c50ee6..2b845737 100644 --- a/src/Portal.js +++ b/src/Portal.js @@ -29,23 +29,23 @@ export default class Portal extends React.Component { } createContainer() { - this.portalContainer = this.props.getContainer(); + this._container = this.props.getContainer(); this.forceUpdate(); } removeContainer() { - if (this.portalContainer) { - this.portalContainer = null; + if (this._container) { + this._container.parentNode.removeChild(this._container); } } render() { - if (this.portalContainer) { + if (this._container) { const currentContainer = this.props.getContainer(); - if (currentContainer && this.portalContainer !== currentContainer) { - this.portalContainer = currentContainer; + if (currentContainer && this._container !== currentContainer) { + this._container = currentContainer; } - return ReactDOM.createPortal(this.props.children, this.portalContainer); + return ReactDOM.createPortal(this.props.children, this._container); } return null; } From dd2a92172472a31c45a3b2058c5d6acfcc293291 Mon Sep 17 00:00:00 2001 From: binyellow <571704908@qq.com> Date: Wed, 25 Mar 2020 11:44:21 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E5=8E=BB=E9=99=A4=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E4=BE=9D=E8=B5=96=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B=EF=BC=8C=E5=88=A4=E6=96=AD=E7=88=B6?= =?UTF-8?q?=E5=AE=B9=E5=99=A8=E5=8F=98=E5=8C=96=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 - tests/container.test.js | 37 ++++++++++++++++--------------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 79ee33e3..e564828b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "create-react-class": "^15.6.3", "enzyme": "^3.10.0", "eslint": "^6.6.0", - "eslint-plugin-react-hooks": "^2.5.1", "father": "^2.14.0", "np": "^5.0.3", "react": "^16.2.0", diff --git a/tests/container.test.js b/tests/container.test.js index a8042491..5b7f4178 100644 --- a/tests/container.test.js +++ b/tests/container.test.js @@ -2,36 +2,31 @@ import React from 'react'; import { mount } from 'enzyme'; import PortalWrapper from '../src/PortalWrapper'; -const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout)); - describe('container', () => { it('Same function returns different DOM', async () => { - let root = document.getElementById('root'); - if (!root) { - root = document.createElement('div', { id: 'root' }); - root.id = 'root'; - document.body.appendChild(root); - } mount(
Hello
World
, - { attachTo: root }, ); - const holdContainer = { - container: document.getElementById('dom1'), - }; - const getContainer = () => holdContainer.container; - const wrapper = mount( - - {() => 'Content'} + const portal = mount( + + {() =>
Content
}
, ); - expect(wrapper).toMatchSnapshot(); - await delay(1000); - holdContainer.container = document.getElementById('dom2'); - wrapper.setProps({ 'data-only-trigger-re-render': true }); - expect(wrapper).toMatchSnapshot(); + const oldWrapper = portal.parent(); + portal.setProps({ + visible: true, + getContainer: document.getElementById('dom1'), + }); + const wrapperDom1 = portal.parent(); + expect(oldWrapper !== wrapperDom1).toEqual(true); + portal.setProps({ + visible: true, + getContainer: document.getElementById('dom2'), + }); + const wrapperDom2 = portal.parent(); + expect(wrapperDom1 !== wrapperDom2).toEqual(true); }); }); From 917b036167a93a459c7f8a051fe5e59f35159486 Mon Sep 17 00:00:00 2001 From: binyellow <571704908@qq.com> Date: Wed, 25 Mar 2020 20:34:26 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Portal.js | 4 ---- tests/container.test.js | 47 +++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/Portal.js b/src/Portal.js index 2b845737..cd2f5836 100644 --- a/src/Portal.js +++ b/src/Portal.js @@ -9,10 +9,6 @@ export default class Portal extends React.Component { didUpdate: PropTypes.func, }; - static defaultProps = { - didUpdate: false, - }; - componentDidMount() { this.createContainer(); } diff --git a/tests/container.test.js b/tests/container.test.js index 5b7f4178..cbf77a1d 100644 --- a/tests/container.test.js +++ b/tests/container.test.js @@ -3,30 +3,35 @@ import { mount } from 'enzyme'; import PortalWrapper from '../src/PortalWrapper'; describe('container', () => { + let div1; + let div2; + beforeAll(() => { + div1 = document.createElement('div'); + div1.id = 'dom1'; + div2 = document.createElement('div'); + div2.id = 'dom2'; + document.body.appendChild(div1); + document.body.appendChild(div2); + }); + afterAll(() => { + document.body.removeChild(div1); + document.body.removeChild(div2); + }); it('Same function returns different DOM', async () => { - mount( -
-
Hello
-
World
-
, - ); - const portal = mount( - + const wrapper = mount( + document.getElementById('dom1')} + > {() =>
Content
}
, ); - const oldWrapper = portal.parent(); - portal.setProps({ - visible: true, - getContainer: document.getElementById('dom1'), - }); - const wrapperDom1 = portal.parent(); - expect(oldWrapper !== wrapperDom1).toEqual(true); - portal.setProps({ - visible: true, - getContainer: document.getElementById('dom2'), - }); - const wrapperDom2 = portal.parent(); - expect(wrapperDom1 !== wrapperDom2).toEqual(true); + + expect(document.querySelector('#dom1 #children')).not.toBeNull(); + + wrapper.setProps({ getContainer: () => document.getElementById('dom2') }); + + expect(document.querySelector('#dom1 #children')).toBeNull(); + expect(document.querySelector('#dom2 #children')).not.toBeNull(); }); }); From e7e5b460adb40c4932407b39342a7d78837038c5 Mon Sep 17 00:00:00 2001 From: binyellow <571704908@qq.com> Date: Thu, 2 Apr 2020 11:26:31 +0800 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0container?= =?UTF-8?q?=E5=85=88=E7=A7=BB=E9=99=A4=E4=B8=8A=E6=AC=A1=E7=9A=84=E7=BB=93?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Portal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Portal.js b/src/Portal.js index cd2f5836..4d24e49c 100644 --- a/src/Portal.js +++ b/src/Portal.js @@ -39,6 +39,7 @@ export default class Portal extends React.Component { if (this._container) { const currentContainer = this.props.getContainer(); if (currentContainer && this._container !== currentContainer) { + this.removeContainer(); this._container = currentContainer; } return ReactDOM.createPortal(this.props.children, this._container);