Skip to content

fix(layout): skip layout updates when container size is 0x0#2269

Open
sharabai wants to merge 1 commit intoShopify:mainfrom
sharabai:fix/recycler-view-zero-size-early-return
Open

fix(layout): skip layout updates when container size is 0x0#2269
sharabai wants to merge 1 commit intoShopify:mainfrom
sharabai:fix/recycler-view-zero-size-early-return

Conversation

@sharabai
Copy link
Copy Markdown

@sharabai sharabai commented May 4, 2026

Description

Fixes #2231

When FlashList is mounted inside a screen rendered by @react-navigation/stack on web, pushing a new screen on top of it transiently measures FlashList's container as 0x0. The two layout useLayoutEffects in RecyclerView then run with those bogus dimensions: the first overwrites the window/layout params with zeros, and the second walks every viewHolderRef and rewrites item layouts. The downstream effect is that every renderItem re-runs — including offscreen items — which defeats recycling and causes the perf regression in the linked Snack repro.

This PR adds two early returns inside src/recyclerview/RecyclerView.tsx:

  1. In the post-mount layout effect: if the outer container measures 0x0, store that size in containerViewSizeRef and bail out before calling recyclerViewManager.updateLayoutParams(...).
  2. In the per-item layout effect: if containerViewSizeRef.current is 0x0, bail out before iterating refHolder and rewriting layouts.

Once the screen is brought back into view and the container regains a non-zero size, the normal layout path resumes on the next layout pass — no items are dropped or re-mounted.

This is the same patch Expensify currently ships against @shopify/flash-list@2.3.0 for the same root cause discussed in #1816, and it removes the need for consumers to remember to toggle a Navigator-level workaround at every call site.

Reviewers' hat-rack 🎩

  • Confirm the first early return still writes containerViewSizeRef.current = outerViewSize before bailing, so the second effect can detect the 0x0 state.
  • Reproduce Rendering of all data when navigating with @react-navigation/stack #2231 against main using the Snack from the issue, then re-run against this branch and verify offscreen items stop re-rendering when a stack screen is pushed on top.
  • Verify there's no regression on lists that legitimately mount with non-zero size on the first measurement (mobile + web), i.e. the fast path is unchanged.
  • Sanity-check that layout converges on the next non-zero measurement after the container is restored — items shouldn't be left half-measured.

Screenshots or videos

After-fix recording:

fixed.navigation.mp4

@sharabai sharabai force-pushed the fix/recycler-view-zero-size-early-return branch from b09e407 to e53ef80 Compare May 4, 2026 16:05
@sharabai
Copy link
Copy Markdown
Author

sharabai commented May 4, 2026

CLA is signed.

@sharabai sharabai force-pushed the fix/recycler-view-zero-size-early-return branch from e53ef80 to b1347f3 Compare May 4, 2026 16:09
@sharabai
Copy link
Copy Markdown
Author

sharabai commented May 4, 2026

@naqvitalha could you take a look at this PR when you have some free time on your hands?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rendering of all data when navigating with @react-navigation/stack

1 participant