Guides

Retool List View Component: Tips, Limits & Workarounds

OTC Team··5 min read
Retool List View Component: Tips, Limits & Workarounds

Retool's List View component has seen major improvements recently, and builders are putting it to work for everything from editable product tables to chat interfaces and grouped reports. But as teams push the component further, a clear set of Retool List View component tips and limitations has emerged from the community. Whether you're hitting the scope barrier, struggling with write-back, or watching scroll bars flicker in a drawer frame, this guide breaks down the real-world friction points — and how to get past them.

What Is the Retool List View Component Used For?

The List View renders a repeating set of components bound to a data array — think of it as a dynamic, templated container. Builders are using it for:

  • Editable lists of records (products, to-dos, form entries) with write-back to a database
  • Chat conversation displays with virtualized scrolling for large message histories
  • Grouped, nested reports replacing legacy Access-style layouts
  • Drag-and-drop reorderable lists stored in a database

The new version delivers a significant performance boost over the old component, especially when rendering many input components simultaneously. Long lists that previously caused multi-hundred-millisecond input lag now render and respond quickly.

The Scope Barrier: Why You Can't Access List View Children from Outside

The most commonly reported frustration is the scope barrier. Components inside a List View are scoped to each repeated row — you cannot reference them directly from outside the list. This makes it harder to:

  • Trigger a global save button that reads all current input values across rows
  • Reset individual child components programmatically after reordering rows
  • Run a single query that aggregates changes from every row at once

The workaround most builders land on is maintaining a temporary state variable as the source of truth. Every interaction inside the list (text edits, reorders, deletions) writes immediately to the temp state via event handlers and custom scripts. On save, you write the entire state object back to the database in one query — not row by row.

How to Set Up Write-Back from Retool List View

There are two common write-back patterns, each with trade-offs:

  • Option A — Per-component onChange: Each input inside the list fires a Change event handler that updates a single value in a temp state. This feels real-time but requires careful temp variable management and can become tedious to wire up across many input types.
  • Option B — Batch save on button click: All edits accumulate in temporary state. A single "Save" button triggers one query that writes the full updated array to the database. More setup upfront, but far easier to reason about and debug.

Option B is the more scalable pattern, especially when rows contain dynamic attribute types (numbers, dates, strings) that vary per record. To make this work cleanly, structure your temp state to mirror a changesetArray — an array of objects where each object represents the current state of one row, keyed by a stable row ID.

The Component State Reset Problem After Reordering

This is a subtle but critical bug-like behavior: if a user edits a text input in row 2, then reorders rows 1 and 2, the input in the new row 1 position will still display the user-typed value — not the default value of the data now occupying that slot. Retool tracks component state by position, not by the underlying data record.

In the old List View, you could call a reset on individual child components. That capability is gone in the new version. The cleanest workaround is to avoid relying on component default values entirely — always drive displayed values from your temp state, and update the temp state on every user interaction. This keeps the component's visual state and your data state in sync regardless of reordering.

Missing Features Builders Are Waiting On

  • Module embedding: You cannot embed a module inside a List View. This forces builders to recreate list contents from scratch in every app instead of reusing modular components — a major DRY violation.
  • onChange event on the List View itself: The List View lacks an onChange() handler at the container level, which complicates triggering scroll behavior or downstream actions when the list data changes.
  • Dynamic disable: There is currently no way to dynamically disable the entire List View component, making loading and permission states harder to manage.
  • A universal input component: Builders rendering rows with mixed data types (dates, numbers, strings) must stack multiple hidden input components per row and toggle visibility with logic. A single polymorphic input that accepts a type prop from data would eliminate this pattern entirely.
  • Built-in reordering: Drag-to-reorder is not natively supported. Builders are hacking it in manually with move-up/move-down buttons and array manipulation in temp state.

Scroll Bar Issues in Modals and Drawer Frames

If you're rendering a List View inside a modal or drawerFrame, expect scroll bar headaches. The new component creates its own scroll context per nested list, meaning:

  • PDF exports via utils.downloadPage() only capture the visible portion of the list, not the full scrollable content
  • Nested lists each get their own scroll bar, cluttering report-style layouts
  • In drawer frames, selecting a child component can trigger rapid scroll bar flickering that makes the editor difficult to use — clicking a parent or child component in the Component Tree stops it

For PDF export use cases, consider flattening your data before rendering or using a non-virtualized layout with overflow visible on the parent container.

Bottom Line

Retool's updated List View is a genuine step forward in performance and flexibility, but it's not yet a complete solution for complex editable list UIs. The scope barrier, missing onChange handler, lack of module support, and component state issues after reordering are real blockers for production builds. Until these gaps are closed, the most reliable pattern is: temp state as source of truth, batch writes on user action, and zero reliance on component-level default values for display logic.

Ready to build?

We scope, design, and ship your Retool app — fast.

Ready to ship your first tool?