diff --git a/src/diff/children.js b/src/diff/children.js index ba2730478c..84d550e8ae 100644 --- a/src/diff/children.js +++ b/src/diff/children.js @@ -398,8 +398,9 @@ function findMatchingIndex( // if the oldVNode was null or matched, then there could needs to be at least // 1 (aka `remainingOldChildren > 0`) children to find and compare against. let shouldSearch = + (typeof type !== 'function' || type === Fragment || key) && remainingOldChildren > - (oldVNode != null && (oldVNode._flags & MATCHED) === 0 ? 1 : 0); + (oldVNode != null && (oldVNode._flags & MATCHED) === 0 ? 1 : 0); if ( oldVNode === null || diff --git a/test/browser/render.test.js b/test/browser/render.test.js index 96bef10bb0..39b0ad86ba 100644 --- a/test/browser/render.test.js +++ b/test/browser/render.test.js @@ -1786,6 +1786,37 @@ describe('render()', () => { ); }); + // #2949 + it('should not swap unkeyed chlildren', () => { + class X extends Component { + constructor(props) { + super(props); + this.name = props.name; + } + render() { + return

{this.name}

; + } + } + + function Foo({ condition }) { + return ( +
+ {condition ? '' : } + {condition ? : ''} +
+ ); + } + + render(, scratch); + expect(scratch.textContent).to.equal('A'); + + render(, scratch); + expect(scratch.textContent).to.equal('B'); + + render(, scratch); + expect(scratch.textContent).to.equal('A'); + }); + it('handle shuffled (stress test)', () => { function randomize(arr) { for (let i = arr.length - 1; i > 0; i--) {