Skip to content

Studio Data pillar grid issues a duplicate find() on every render — the columns array identity is in ListView's fetch dependency chain #4567

Description

@yinlianghui

Measured while verifying #4549 (the slot refreshKey card). Filed separately: it is upstream of that slot and orthogonal to it.

What was measured

Driving renderStudioGridList (the Data pillar's renderListView slot) with a real ListView and a counting dataSource, then forcing three re-renders that change nothing — same refresh signal value, same column names:

t=600ms find=1              (mount settled)
--- 3 rerenders (same counter) ---
t+50ms find=4

One extra find() per render. Re-running the identical harness with the columns array hoisted to a stable identity and changing nothing else:

t=600ms find=1
--- 3 rerenders (same counter) ---
t+300ms find=1
--- bump ---
t++50ms find=2

Zero extra fetches on re-render, and the refresh signal still refetches exactly once. So the trigger is the identity of schema.columns, not its contents.

Why it fires in Studio

ListView derives its expand fields from schema.columns, and that derivation sits in the fetch effect's dependency array by identity (packages/plugin-list/src/ListView.tsx:1609expandFields among the deps). A fresh array literal per render therefore re-runs the fetch.

The Studio Data pillar hands it exactly that. packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:2600 builds the object-view schema inline:

table: {
  fields: readFields(objDraft.fields).entries.map(...).filter(...),
},

.map().filter() allocates a new array on every render, plugin-view's ObjectView forwards it to the slot as columns (packages/plugin-view/src/ObjectView.tsx, the renderListView payload), and the slot spreads it into ListView's schema. The Studio grid re-renders constantly (its whole schema is a fresh object literal each time), so this is a steady-state duplicate-query source against the backend, not a rare edge.

Impact

Every keystroke-level re-render of the Data pillar issues another list query. Invisible in the UI — the rows just repaint with the same data — so it reads as "working" while multiplying backend load.

Worth deciding

Two candidate fixes, opposite ends:

  1. Producer side — memoize the table.fields array in StudioDesignSurface (React.useMemo keyed on the draft's field names). Narrow, but only fixes this one consumer; any other caller passing a fresh array has the same defect.
  2. Consumer side — have ListView depend on the column names' value (a joined key) rather than the array identity. Fixes every caller at once, but it is a plugin-list change and needs care that a genuinely changed column set still refetches.

(2) looks like the real fix, since the identity contract is currently unstated and every caller has to guess it. Someone who owns plugin-list's fetch effect should judge.

Refs #4549, #4528.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions