Repository navigation
fix: clamp initialItemCount to data length when data prop is used - #1461
Conversation
When initialItemCount exceeds data.length, buildListStateFromItemCount creates phantom items with data: undefined. These phantom items produce zero-height DOM elements, triggering Zero-sized element console errors. Clamp the adjusted count to data.length when the data prop is provided (non-empty array), so Virtuoso never renders more initial items than exist in the data array. When data is not used (totalCount-only mode), the existing behavior is preserved. Relates to petyosi#1060 -- the prior fix (PR petyosi#1061) addressed a ResizeObserver timing issue in useSize, but this separate code path in buildListStateFromItemCount was never patched.
🦋 Changeset detectedLatest commit: 797e7a5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This is technically a valid fix, but can you explain why would the library consumer pass such a value? As in, is this purely defensive improvement for an invalid value? |
@petyosi It's not purely defensive, this is a natural mismatch that happens when <Virtuoso
data={results} // could be 3 items
initialItemCount={10} // generous default to fill viewport on first paint
itemContent={(i, item) => <div>{item.name}</div>}
/>This isn't an |
52af5c1 to
6acb745
Compare
|
We pass
When does Production trace of one crash: list renders 3 items (cell = 3) → user opens another native screen, webview hidden before measurement completes → a background refresh on page-show removes one item → the same render publishes So the clamp in this PR is not defensive hardening for an invalid prop — it is the minimal invariant that makes the library's own one-publish-cycle staleness harmless. We would really appreciate it landing. Two small notes on the patch itself (optional, not blocking):
|
Follow-up to the data.length clamp, covering the remaining gaps: - clamp the count to the data remaining after initialTopMostItemIndex, which could still read past the end of the array - treat an explicitly empty data array as zero items, while omitted data keeps the index-driven initial rendering - add initialItemCount to the list state combineLatest so publishing it recomputes immediately; previously it was read from a stale cell and a data shrink in the same render cycle produced undefined items, crashing computeItemKey in unmeasured (hidden) viewports - add a 13-input combineLatest overload to urx
…m-count-to-data-length
 <h3>Snyk has created this PR to upgrade react-virtuoso from 4.18.14 to 4.18.15.</h3> :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project. <hr/> - The recommended version is **1 version** ahead of your current version. - The recommended version was released **23 days ago**. #### Breaking Change Risk  > **Notice:** This assessment is enhanced by AI. <details> <summary><b>Release notes</b></summary> <br/> <details> <summary>Package name: <b>react-virtuoso</b></summary> <ul> <li> <b>4.18.15</b> - <a href="https://redirect.github.com/petyosi/react-virtuoso/releases/tag/react-virtuoso%404.18.15">2026-09-22</a></br><h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/petyosi/react-virtuoso/pull/1461" data-hovercard-type="pull_request" data-hovercard-url="/petyosi/react-virtuoso/pull/1461/hovercard">#1461</a> <a href="https://redirect.github.com/petyosi/react-virtuoso/commit/364c071dc1e044b52d1cfbce65851440d39be77e"><code>364c071</code></a> Thanks <a href="https://redirect.github.com/aehmt">@ aehmt</a>! - Fixed "Zero-sized element, this should not happen" error when <code>initialItemCount</code> exceeds the available <code>data</code>. The initial list state builder now clamps the item count to the data remaining after <code>initialTopMostItemIndex</code>, and renders no items when <code>data</code> is explicitly empty, preventing phantom items with <code>undefined</code> data from being rendered. <code>initialItemCount</code> also became a reactive input of the list state computation, so changing it after mount recomputes the list instead of leaving stale state until an unrelated update.</li> </ul> </li> <li> <b>4.18.14</b> - 2026-09-20 </li> </ul> from <a href="https://redirect.github.com/petyosi/react-virtuoso/releases">react-virtuoso GitHub release notes</a> </details> </details> --- > [!IMPORTANT] > > - Check the changes in this PR to ensure they won't cause issues with your project. > - This PR was automatically created by Snyk using the credentials of a real user. --- **Note:** _You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs._ **For more information:** <img src="https://api.segment.io/v1/pixel/track?data=eyJ3cml0ZUtleSI6ImZha2Uta2V5IiwiYW5vbnltb3VzSWQiOiJkZWU2Njk4NC1iOWViLTQ0ODktYjBhOS01NWRjMTJiNTczN2MiLCJldmVudCI6IlBSIHZpZXdlZCIsInByb3BlcnRpZXMiOnsicHJJZCI6ImRlZTY2OTg0LWI5ZWItNDQ4OS1iMGE5LTU1ZGMxMmI1NzM3YyJ9fQ==" width="0" height="0"/> > - 🧐 [View latest project report](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f?utm_source=github&utm_medium=referral&page=upgrade-pr) > - 📜 [Customise PR templates](https://docs.snyk.io/scan-using-snyk/pull-requests/snyk-fix-pull-or-merge-requests/customize-pr-templates?utm_source=&utm_content=fix-pr-template) > - 🛠 [Adjust upgrade PR settings](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f/settings/integration?utm_source=github&utm_medium=referral&page=upgrade-pr) > - 🔕 [Ignore this dependency or unsubscribe from future upgrade PRs](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f/settings/integration?pkg=react-virtuoso&utm_source=github&utm_medium=referral&page=upgrade-pr#auto-dep-upgrades) [//]: # 'snyk:metadata:{"breakingChangeRiskLevel":"medium","FF_showPullRequestBreakingChanges":true,"FF_showPullRequestBreakingChangesWebSearch":false,"customTemplate":{"variablesUsed":[],"fieldsUsed":[]},"dependencies":[{"name":"react-virtuoso","from":"4.18.14","to":"4.18.15"}],"env":"prod","hasFixes":false,"isBreakingChange":false,"isMajorUpgrade":false,"issuesToFix":[],"prId":"dee66984-b9eb-4489-b0a9-55dc12b5737c","prPublicId":"dee66984-b9eb-4489-b0a9-55dc12b5737c","packageManager":"npm","priorityScoreList":[],"projectPublicId":"e1f199d3-0a16-4ac7-a9a1-528e774fc41f","projectUrl":"https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f?utm_source=github&utm_medium=referral&page=upgrade-pr","prType":"upgrade","templateFieldSources":{"branchName":"default","commitMessage":"default","description":"default","title":"default"},"templateVariants":[],"type":"auto","upgrade":[],"upgradeInfo":{"versionsDiff":1,"publishedDate":"2026-09-22T18:25:30.741Z"},"vulns":[]}'
 <h3>Snyk has created this PR to upgrade react-virtuoso from 4.18.15 to 4.18.16.</h3> :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project. <hr/> - The recommended version is **1 version** ahead of your current version. - The recommended version was released **24 days ago**. #### Breaking Change Risk  > **Notice:** This assessment is enhanced by AI. <details> <summary><b>Release notes</b></summary> <br/> <details> <summary>Package name: <b>react-virtuoso</b></summary> <ul> <li> <b>4.18.16</b> - <a href="https://redirect.github.com/petyosi/react-virtuoso/releases/tag/react-virtuoso%404.18.16">2026-09-29</a></br><h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/petyosi/react-virtuoso/pull/1512" data-hovercard-type="pull_request" data-hovercard-url="/petyosi/react-virtuoso/pull/1512/hovercard">#1512</a> <a href="https://redirect.github.com/petyosi/react-virtuoso/commit/b7238f3856ae51afcbf8045a7c61b8f1c42e9a0c"><code>b7238f3</code></a> Thanks <a href="https://redirect.github.com/cpruijsen">@ cpruijsen</a>! - Map <code>skipAnimationFrameInResizeObserver</code> through TableVirtuoso's urx optional props so the table resize observer consumes it instead of leaving the leftover prop on the scroller DOM.</li> </ul> </li> <li> <b>4.18.15</b> - <a href="https://redirect.github.com/petyosi/react-virtuoso/releases/tag/react-virtuoso%404.18.15">2026-09-22</a></br><h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/petyosi/react-virtuoso/pull/1461" data-hovercard-type="pull_request" data-hovercard-url="/petyosi/react-virtuoso/pull/1461/hovercard">#1461</a> <a href="https://redirect.github.com/petyosi/react-virtuoso/commit/364c071dc1e044b52d1cfbce65851440d39be77e"><code>364c071</code></a> Thanks <a href="https://redirect.github.com/aehmt">@ aehmt</a>! - Fixed "Zero-sized element, this should not happen" error when <code>initialItemCount</code> exceeds the available <code>data</code>. The initial list state builder now clamps the item count to the data remaining after <code>initialTopMostItemIndex</code>, and renders no items when <code>data</code> is explicitly empty, preventing phantom items with <code>undefined</code> data from being rendered. <code>initialItemCount</code> also became a reactive input of the list state computation, so changing it after mount recomputes the list instead of leaving stale state until an unrelated update.</li> </ul> </li> </ul> from <a href="https://redirect.github.com/petyosi/react-virtuoso/releases">react-virtuoso GitHub release notes</a> </details> </details> --- > [!IMPORTANT] > > - Check the changes in this PR to ensure they won't cause issues with your project. > - This PR was automatically created by Snyk using the credentials of a real user. --- **Note:** _You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs._ **For more information:** <img src="https://api.segment.io/v1/pixel/track?data=eyJ3cml0ZUtleSI6ImZha2Uta2V5IiwiYW5vbnltb3VzSWQiOiJiOTQxODU0OC1hNDU3LTQ2YjgtOTQxNi1iMTdjMzM1ZWFiNTkiLCJldmVudCI6IlBSIHZpZXdlZCIsInByb3BlcnRpZXMiOnsicHJJZCI6ImI5NDE4NTQ4LWE0NTctNDZiOC05NDE2LWIxN2MzMzVlYWI1OSJ9fQ==" width="0" height="0"/> > - 🧐 [View latest project report](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f?utm_source=github&utm_medium=referral&page=upgrade-pr) > - 📜 [Customise PR templates](https://docs.snyk.io/scan-using-snyk/pull-requests/snyk-fix-pull-or-merge-requests/customize-pr-templates?utm_source=&utm_content=fix-pr-template) > - 🛠 [Adjust upgrade PR settings](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f/settings/integration?utm_source=github&utm_medium=referral&page=upgrade-pr) > - 🔕 [Ignore this dependency or unsubscribe from future upgrade PRs](https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f/settings/integration?pkg=react-virtuoso&utm_source=github&utm_medium=referral&page=upgrade-pr#auto-dep-upgrades) [//]: # 'snyk:metadata:{"breakingChangeRiskLevel":"low","FF_showPullRequestBreakingChanges":true,"FF_showPullRequestBreakingChangesWebSearch":false,"customTemplate":{"variablesUsed":[],"fieldsUsed":[]},"dependencies":[{"name":"react-virtuoso","from":"4.18.15","to":"4.18.16"}],"env":"prod","hasFixes":false,"isBreakingChange":false,"isMajorUpgrade":false,"issuesToFix":[],"prId":"b9418548-a457-46b8-9416-b17c335eab59","prPublicId":"b9418548-a457-46b8-9416-b17c335eab59","packageManager":"npm","priorityScoreList":[],"projectPublicId":"e1f199d3-0a16-4ac7-a9a1-528e774fc41f","projectUrl":"https://app.eu.snyk.io/org/antigravity-awesome-skills-default/project/e1f199d3-0a16-4ac7-a9a1-528e774fc41f?utm_source=github&utm_medium=referral&page=upgrade-pr","prType":"upgrade","templateFieldSources":{"branchName":"default","commitMessage":"default","description":"default","title":"default"},"templateVariants":[],"type":"auto","upgrade":[],"upgradeInfo":{"versionsDiff":1,"publishedDate":"2026-09-29T16:03:47.020Z"},"vulns":[]}'
Bug
When
initialItemCountexceedsdata.length,buildListStateFromItemCountcreates phantom items withdata: undefined. These phantom items produce zero-height DOM elements, triggering the "Zero-sized element, this should not happen" console error for each one.Reproduction
Console shows
Zero-sized element, this should not happen {child: div}repeated 7 times (10 - 3 = 7 phantom items).Root cause
In
buildListStateFromItemCount(listStateSystem.ts), the item count is not clamped to the data array length:Fix
Clamp
adjustedCounttodata.lengthwhen thedataprop is provided (non-empty array):When
datais not used (totalCount-only mode, wheredatadefaults to[]), the existing behavior is preserved.Relation to #1060
This is a separate code path from the issue fixed in #1061. That PR addressed a
ResizeObservertiming issue inuseSize. This fix addressesbuildListStateFromItemCountnever clamping todata.length— a bug that was present before and after #1061. The continued reports on #1060 (e.g., this comment on v4.8.0+) suggest this code path was the remaining unfixed cause.Test added
Added a test in
listSystem.test.tsverifying thatinitialItemCountis clamped todata.lengthand no items haveundefineddata.