diff --git a/src/diff/index.js b/src/diff/index.js index 63b59ee8c6..3c4b96929f 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -147,6 +147,9 @@ export function diff( c._vnode = newVNode; newVNode._dom = oldVNode._dom; newVNode._children = oldVNode._children; + newVNode._children.forEach(vnode => { + if (vnode) vnode._parent = newVNode; + }); if (c._renderCallbacks.length) { commitQueue.push(c); } diff --git a/test/browser/lifecycles/shouldComponentUpdate.test.js b/test/browser/lifecycles/shouldComponentUpdate.test.js index ae0a6a66e9..6b5f18709a 100644 --- a/test/browser/lifecycles/shouldComponentUpdate.test.js +++ b/test/browser/lifecycles/shouldComponentUpdate.test.js @@ -857,4 +857,60 @@ describe('Lifecycle methods', () => { // 'id: 3a: 25b: 1000id: 1a: 5id: 2a: 50b: 10b: 100.insertBefore(
b: 100,
id: 2)' // ]); }); + + it('should maintain the order if memoised component initially rendered empty content', () => { + let showText, updateParent; + class Child extends Component { + constructor(props) { + super(props); + this.state = { + show: false + }; + showText = () => this.setState({ show: true }); + } + render(props, { show }) { + if (!show) return null; + + return
Component
; + } + } + + class Memoized extends Component { + shouldComponentUpdate() { + return false; + } + render() { + return ; + } + } + class Parent extends Component { + constructor(props) { + super(props); + updateParent = () => this.setState({}); + } + render() { + return ( + +
Before
+ +
After
+
+ ); + } + } + + render(, scratch); + expect(scratch.innerHTML).to.equal(`
Before
After
`); + + updateParent(); + rerender(); + expect(scratch.innerHTML).to.equal(`
Before
After
`); + + showText(); + rerender(); + + expect(scratch.innerHTML).to.equal( + `
Before
Component
After
` + ); + }); });