The Simple Trick That Makes a List of 50,000 Render Smoothly

Published: (January 17, 2026 at 07:22 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

Why is rendering 50,000 items bad?

This might seem obvious with such an exaggerated number, but what about a much smaller number like 1,000? The number is arbitrary and doesn’t mean anything because it carries a different weight depending on the device and its resources.

The DOM (Document Object Model) represents the HTML structure of a web page as a tree of nodes and objects. This tree is created by the browser’s rendering engine – we don’t have to manage it directly. When DOM nodes change, the browser may need to:

  1. Re‑calculate styles
  2. Re‑layout the page
  3. Re‑paint parts of the page

The more nodes involved, the more expensive this process becomes.

The Virtual DOM

The Virtual DOM is an in‑memory representation of the real DOM that does not interact with the browser’s rendering engine. When a state change occurs, React first updates the Virtual DOM instead of the real DOM. It then uses a diffing algorithm to identify the necessary changes. This selective mechanism significantly improves performance and predictability by:

  • Reducing unnecessary re‑renders
  • Minimising direct manipulation of the real DOM

Example: a <select> of shipping ports

<select>
  <option value="NLRTM">Rotterdam</option>
  <option value="DEHAM">Hamburg</option>
  <option value="FRLAV">Le Havre</option>
</select>

The “Rotterdam” option in the Virtual DOM (simplified for clarity) looks like this:

{
  type: 'option',
  props: {
    value: 'NLRTM',
    children: 'Rotterdam'
  },
  key: null,
  stateNode: HTMLOptionElement, // Reference to the real DOM node
  return: FiberNode,            // Pointer to the parent
  sibling: FiberNode,           // Pointer to "Hamburg"
  // ... dozens of other internal reconciliation properties
}

As you can see, the metadata React needs to manage for each node is significant. If we have 1,000 ports in our <select>, React’s memory fills up with 1,000 of these objects. Every time this component renders, React may have to traverse a large linked list of objects, in addition to the JavaScript and C++ objects created by the browser engine.

While 1,000 items won’t crash a modern machine, it can exceed the 16 ms frame budget, causing dropped frames—especially when combined with user interactions like scrolling or typing. The problem is even worse on mobile devices, which have far more limited resources. Scrolling a long, non‑virtualized list on mobile often feels heavy and results in noticeable jank.

Note: A complex web page consists of many components, each with its own overhead. Designing, developing, and testing components in isolation can hide the cumulative cost.

Why memoization isn’t enough

Most React developers reach for memoization, and it’s understandable: fewer re‑renders sounds like less work. However, memoization only stops React from re‑running component code; it does not reduce how much the browser has to draw. If 1,000 elements exist, the browser still has to layout and paint all 1,000 elements.

During interactions like scrolling, even if React doesn’t re‑render, the browser must still calculate layout and paint every visible element on each frame. With enough elements, that alone is enough to cause jank.

Render less, not faster

In an ideal world, the API you consume would let you paginate, filter, or search to reduce the number of results returned. For the port‑selector example, instead of returning every port in the world (or even every port in Europe), the API could return only the ports for a selected country—perhaps 50 options.

But you don’t always control the API:

  • An internal API may be owned by another team.
  • A third‑party API is entirely out of your hands.

In those cases, the responsibility shifts to the UI. Even if you receive a large dataset, you don’t have to render all of it at once. Rendering less might mean:

  • Showing only what’s visible on screen.
  • Delaying work until the user interacts.
  • Replacing large dropdowns with search‑driven interfaces.

The goal isn’t to make rendering faster; it’s to avoid doing unnecessary work in the first place. Reducing the number of elements the browser has to handle makes everything else cheaper by default.

We achieve this with a technique called windowing (also known as virtualization).

What is Virtualization?

The term sounds more intimidating than it actually is. Virtualization means rendering only what’s visible in the viewport. The viewport can be any element that displays a list—so for a <Select> component, it’s the scrollable container that shows the options.

If the viewport displays six elements, the browser renders exactly six elements, regardless of how large the underlying dataset is. We’re not merely hiding elements; we’re removing them from the DOM when they’re off‑screen.

Virtualization illustration

Caveat: Because off‑screen items are physically removed from the DOM, native browser features like “Find on Page” won’t see them. Additionally, certain interactions (e.g., keyboard navigation that expects all options to be present) may need extra handling.

Bottom line

  • Big lists can cripple performance, especially on constrained devices.
  • Memoization helps with React’s work but does nothing for the browser’s layout/paint cost.
  • Virtualization/windowing removes off‑screen elements from the DOM, dramatically reducing the work the browser must do.

Use virtualization whenever you have large collections, and fall back to pagination or server‑side filtering when possible. This keeps your UI snappy and your users happy.

Summary

Whether you’re building a chat feature, a social feed, or even just a Select component, virtualization can make a huge difference in how smooth your app feels. If you want to try it out, I recommend using a well‑established library. For React, the following are solid choices:

If you found this post useful and want to support more content like this, you can:

Cover image by Edson Junior on Unsplash.

Back to Blog

Related posts

Read more »

How React works?

Component is the base React app is made of components. A component is just a JavaScript function that returns UI. javascript function App { return Hello ; } JS...

Optimizing Re-Renders by Moving State

Introduction One way to improve performance and reduce unnecessary re‑renders is by lowering the state, especially if it only affects a specific part of the co...