In Previous post, I shared how we tackled performance issues in our React application by identifying and addressing unnecessary re-renders.
But in our case, we had a more specific challenge:
- The page had up to 200 editable list items shown at once
- Pagination wasn’t an option — users needed to interact with all items together
- Even after optimizing rendering logic, we still couldn’t hit target performance metrics or deliver a smooth UX
So we started thinking:
Can we reduce the number of components rendered without breaking the user experience?
This led us to consider infinite scrolling and virtual scrolling.
What is Infinite Scroll?
Infinite scroll is a technique where more items are dynamically loaded as the user scrolls toward the end of the list.
How it works:
- You initially render a small number of items (say 20).
- As the user scrolls near the bottom, a trigger fires (e.g. intersection observer or scroll event).
- A request is made to fetch the next batch of data.
- The newly fetched items are appended to the existing list, increasing the number of DOM elements.
This approach is great when:
- Users are browsing or consuming content (like a social feed)
- Lazy loading is acceptable
- The total number of items is unknown or very large
But the downside:
- DOM keeps growing as you scroll — which can slow down the app over time
- Doesn’t help if your users need to interact with the full list, not just browse
What is Virtual Scroll?
Virtual scroll, on the other hand, renders only what’s visible in the viewport (plus a small buffer), and dynamically mounts/unmounts items as the user scrolls.
How it works:
- A container tracks the scroll position
- Only the list items within (or near) the visible area are actually rendered in the DOM
- As you scroll:
- Off-screen components are unmounted
- New components are mounted just-in-time as they enter view
- The full height of the scrollable area is simulated using padding/spacers so the scroll bar still behaves like a normal long list
This technique is perfect when:
- You have a long or infinite list
- Performance and memory usage matter
- You want to avoid bloating the DOM with hundreds of elements
But it’s not free:
- It adds complexity, especially with interactive components like editable forms
- State management between mounts/unmounts needs careful handling
Our Decision: Go with Virtual Scroll
For our use case, virtual scroll made way more sense:
- We didn’t need to change backend API behavior — no offset/limit logic required
- It gave us predictable performance regardless of scroll depth
- Infinite scroll would have caused the DOM to grow endlessly, which is exactly what we were trying to avoid
It was the cleanest way to keep all 200 items usable on one page without actually rendering all 200 at once.
In the next post, I’ll share how we implemented virtual scrolling with TanStack Virtual, and what we learned while integrating it with editable form components.
Stay tuned!
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.