diff --git a/src/diff/index.js b/src/diff/index.js index a8f5774b3f..f7d5c0a068 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -281,7 +281,7 @@ export function unmount(vnode, parentVNode, skipRemove) { } let dom; - if (!skipRemove && vnode._lastDomChild==null) { + if (!skipRemove && typeof vnode.type !== 'function') { skipRemove = (dom = vnode._dom)!=null; } diff --git a/test/browser/components.test.js b/test/browser/components.test.js index 6ebb8fab3a..18ec0719c3 100644 --- a/test/browser/components.test.js +++ b/test/browser/components.test.js @@ -183,6 +183,92 @@ describe('Components', () => { expect(scratch.innerHTML).to.equal('
Hello
'); }); + it('should also update the current dom', () => { + let trigger; + + class A extends Component { + constructor(props) { + super(props); + this.state = { show: false }; + trigger = this.set = this.set.bind(this); + } + + set() { + this.setState({ show: true }); + } + + render() { + return this.state.show ?
A
: null; + } + } + + const B = () =>

B

; + + render( +
+ + +
, + scratch + ); + expect(scratch.innerHTML).to.equal('

B

'); + + trigger(); + rerender(); + expect(scratch.innerHTML).to.equal('
A

B

'); + }); + + it('should not orphan children', () => { + let triggerC, triggerA; + const B = () =>

B

; + + // Component with state which swaps its returned element type + class C extends Component { + constructor(props) { + super(props); + this.state = { show: false }; + triggerC = this.set = this.set.bind(this); + } + + set() { + this.setState({ show: true }); + } + + render() { + return this.state.show ?
data
:

Loading

; + } + } + + const WrapC = () => ; + + class A extends Component { + constructor(props) { + super(props); + this.state = { show: false }; + triggerA = this.set = this.set.bind(this); + } + + set() { + this.setState({ show: true }); + } + + render() { + return this.state.show ? : ; + } + } + + render(
, scratch); + expect(scratch.innerHTML).to.equal('

Loading

'); + + triggerC(); + rerender(); + expect(scratch.innerHTML).to.equal('
data
'); + + triggerA(); + rerender(); + expect(scratch.innerHTML).to.equal('

B

'); + }); + it('should render components that don\'t pass args into the Component constructor (unistore pattern)', () => { // Pattern unistore uses for connect: https://git.io/fxRqu function Wrapper() {