Skip to content

Commit 342b50e

Browse files
authored
fix: case where shrinking a list would cause an exception (#4312)
* yikes * fix issue
1 parent a784a62 commit 342b50e

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

src/diff/children.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ export function diffChildren(
116116
childVNode._flags & INSERT_VNODE ||
117117
oldVNode._children === childVNode._children
118118
) {
119+
if (!newDom && oldVNode._dom == oldDom) {
120+
oldDom = getDomSibling(oldVNode);
121+
}
119122
oldDom = insert(childVNode, oldDom, parentDom);
120123
} else if (
121124
typeof childVNode.type == 'function' &&
@@ -241,6 +244,7 @@ function constructNewChildrenArray(newParentVNode, renderResult, oldChildren) {
241244
if (oldVNode._dom == newParentVNode._nextDom) {
242245
newParentVNode._nextDom = getDomSibling(oldVNode);
243246
}
247+
244248
unmount(oldVNode, oldVNode, false);
245249

246250
// Explicitly nullify this position in oldChildren instead of just

test/browser/render.test.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,8 +1481,8 @@ describe('render()', () => {
14811481

14821482
expect(serializeHtml(scratch)).to.equal(
14831483
'<div><p>_B1</p><p>_B2</p><p>_B3</p><h2>_B4</h2><p>_B5</p><p>_B6</p><p>_B7</p><h2>_B8</h2><p>_B9</p><p>_B10</p><p>_B11</p><p>_B12</p><h2>_B13</h2></div>'
1484-
);
1485-
});
1484+
);
1485+
});
14861486

14871487
it('should not crash or repeatedly add the same child when replacing a matched vnode with null (mixed dom-types)', () => {
14881488
const B = () => <div>B</div>;
@@ -1537,4 +1537,48 @@ describe('render()', () => {
15371537
'<div><span>A</span><div>B</div><div>C</div></div>'
15381538
);
15391539
});
1540+
1541+
it('should shrink lists', () => {
1542+
function RenderedItem({ item }) {
1543+
if (item.renderAsNullInComponent) {
1544+
return null;
1545+
}
1546+
1547+
return <div>{item.id}</div>;
1548+
}
1549+
1550+
function App({ list }) {
1551+
return (
1552+
<div>
1553+
{list.map(item => (
1554+
<RenderedItem key={item.id} item={item} />
1555+
))}
1556+
</div>
1557+
);
1558+
}
1559+
1560+
const firstList = [
1561+
{ id: 'One' },
1562+
{ id: 'Two' },
1563+
{ id: 'Three' },
1564+
{ id: 'Four' }
1565+
];
1566+
1567+
const secondList = [
1568+
{ id: 'One' },
1569+
{ id: 'Four', renderAsNullInComponent: true },
1570+
{ id: 'Six' },
1571+
{ id: 'Seven' }
1572+
];
1573+
1574+
render(<App list={firstList} />, scratch);
1575+
expect(scratch.innerHTML).to.equal(
1576+
'<div><div>One</div><div>Two</div><div>Three</div><div>Four</div></div>'
1577+
);
1578+
1579+
render(<App list={secondList} />, scratch);
1580+
expect(scratch.innerHTML).to.equal(
1581+
'<div><div>One</div><div>Six</div><div>Seven</div></div>'
1582+
);
1583+
});
15401584
});

0 commit comments

Comments
 (0)