diff --git a/src/component.js b/src/component.js
index 2270391120..88817c2d10 100644
--- a/src/component.js
+++ b/src/component.js
@@ -103,7 +103,7 @@ export function getDomSibling(vnode, childIndex) {
// Since updateParentDomPointers keeps _dom pointer correct,
// we can rely on _dom to tell us if this subtree contains a
// rendered DOM node, and what the first rendered DOM node is
- return sibling._dom;
+ return sibling._nextDom || sibling._dom;
}
}
diff --git a/src/diff/children.js b/src/diff/children.js
index fdd6a1255c..35874a64e1 100644
--- a/src/diff/children.js
+++ b/src/diff/children.js
@@ -111,6 +111,7 @@ export function diffChildren(
oldVNode = oldChildren[i];
if (oldVNode && oldVNode.key == null && oldVNode._dom) {
if (oldVNode._dom == oldDom) {
+ oldVNode._parent = oldParentVNode;
oldDom = getDomSibling(oldVNode);
}
diff --git a/test/browser/fragments.test.js b/test/browser/fragments.test.js
index fe3a672016..f04a80d3a7 100644
--- a/test/browser/fragments.test.js
+++ b/test/browser/fragments.test.js
@@ -646,6 +646,110 @@ describe('Fragment', () => {
expect(scratch.innerHTML).to.equal('
Hello
');
});
+ it('should preserve order for fragment switching', () => {
+ let set;
+ class Foo extends Component {
+ constructor(props) {
+ super(props);
+ this.state = { isLoading: true, data: null };
+ set = this.setState.bind(this);
+ }
+ render(props, { isLoading, data }) {
+ return (
+
+ HEADER
+ {isLoading ? Loading...
: null}
+ {data ? Content: {data}
: null}
+
+ );
+ }
+ }
+
+ render(, scratch);
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Loading...
'
+ );
+
+ set({ isLoading: false, data: 2 });
+ rerender();
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Content: 2
'
+ );
+ });
+
+ it('should preserve order for nested fragment switching w/ child return', () => {
+ let set;
+ const Wrapper = ({ children }) => {children};
+ class Foo extends Component {
+ constructor(props) {
+ super(props);
+ this.state = { isLoading: true, data: null };
+ set = this.setState.bind(this);
+ }
+ render(props, { isLoading, data }) {
+ return (
+
+ HEADER
+ {isLoading ? Loading...
: null}
+ {data ? Content: {data}
: null}
+
+ );
+ }
+ }
+
+ render(
+
+
+ ,
+ scratch
+ );
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Loading...
'
+ );
+
+ set({ isLoading: false, data: 2 });
+ rerender();
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Content: 2
'
+ );
+ });
+
+ it('should preserve order for nested fragment switching', () => {
+ let set;
+ const Wrapper = () => (
+
+
+
+ );
+ class Foo extends Component {
+ constructor(props) {
+ super(props);
+ this.state = { isLoading: true, data: null };
+ set = this.setState.bind(this);
+ }
+ render(props, { isLoading, data }) {
+ return (
+
+ HEADER
+ {isLoading ? Loading...
: null}
+ {data ? Content: {data}
: null}
+
+ );
+ }
+ }
+
+ render(, scratch);
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Loading...
'
+ );
+
+ set({ isLoading: false, data: 2 });
+ rerender();
+ expect(scratch.innerHTML).to.equal(
+ 'HEADER
Content: 2
'
+ );
+ });
+
it('should preserve state with reordering in multiple levels', () => {
function Foo({ condition }) {
return condition ? (