Repository navigation
fix(plugin-grid,plugin-list): the grid and the list re-read when a harvested query input changes (objectui#10689) - #11280
Conversation
…rvested query input changes (objectui#10689) ObjectGrid's load effect and ListView's fetch effect harvest predicate operands from conditionalFormatting, rowActionDefs and bulkActionDefs into $select, and the grid sends searchableFields as $searchFields, but none of those inputs was in the effect's dependencies. A rule added to a mounted grid or list never had its operand fetched. Each is now keyed by content: the harvested operand names (predicateProjectionKey, the shape groupingProjectionKey already takes) and, on the grid, the $searchFields the query sends (searchFieldsKey). An equal re-render or a style-only rule change does not re-read. ListView's searchableFields was already a dependency on main; it is pinned, not re-edited. Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ Co-authored-by: Claude <noreply@anthropic.com>
…inputs through typed casts, not any (objectui#10689)
The key's inputs are hoisted into plain locals read through
`{ rowActionDefs?: readonly unknown[] }`-shaped casts, the way the grid
already reads `bulkActionDefs` for its diagnostic, so the dependency list
holds simple names. No behaviour change: the same three inputs, the same
content key. It removes the lint warnings the first commit added to both
files (no-explicit-any, and the complex-expression dependency warnings).
Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ
Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Inputs read: card #10689 (body and all four comments: grade ① Derived judgments
② Semver levelTwo changesets,
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #10689
Clause-②: no
ObjectGrid's load effect andListView's fetch effect now re-read when an input their query reads changes, and only then. This is the objectui#10664 family rule ("every input the query reads is in the effect's dependencies"), in PR objectui#10688's shape: each input is keyed by content, as a string compared by value (AGENTS.md #10). What the query selects is unchanged; only when it re-reads moves.The rows, re-derived on
main(18d1a0abd3)ObjectGridload effect)conditionalFormatting(predicate-operand harvest)predicateProjectionKeyrowActionDefs(harvest)predicateProjectionKeybulkActionDefs(harvest)predicateProjectionKeysearchableFields($searchFields)searchFieldsKeyListViewfetch effect)conditionalFormatting(harvest)predicateProjectionKeyrowActionDefs(harvest)predicateProjectionKeybulkActionDefs(harvest)predicateProjectionKeysearchableFields($searchFields)schema.searchableFields, by identity)The keys
predicateProjectionKey, in both files:JSON.stringify(collectPredicateFieldRefs(listViewPredicates({ conditionalFormatting, rowActionDefs, bulkActionDefs }))). It is the same harvest over the same three view-level inputs that the effect runs. It keys on the operand NAMES, the shapegroupingProjectionKeyalready takes forgroupingin the grid, so a rule's style or an action's label costs no round trip. The object-levelactions/userActionsthe effect adds come from the object definition, not the view, and stay outside the key.searchFieldsKey, in the grid: the$searchFieldsthe query sends. It isJSON.stringify(searchableFields)while a term goes out, and''otherwise, because without a term the query does not send them.JSON.stringify(...)strings (sortKey,optionsFilterKey,tableSortKey) or a computed projection (lookupExpandKey). These two keys follow that shape.{ rowActionDefs?: readonly unknown[] }, the way the grid already readsbulkActionDefsfor its diagnostic), so the dependency lists hold simple names. TherowActionDefsread is the objectui#5091 NON-AUTHOR SURFACE exemption, as at the effects' own reads.Red first, then ablation
Red first, at base. The two pin files, at their committed bytes, were run against the source at
18d1a0abd3:Tests 4 failed | 4 passed (8). The four defect rows were red (for the rule,$selectstayed[['id','name']]), and the controls were green.Tests 3 failed | 4 passed (7). The three defect rows were red. The listsearchableFieldspin was green, because that row was already keyed on main.Ablation at head
1842dc0f83, throughablation-replace.mjs. The anchor hit went 1 to 0, and the restore was proven: blob equal to HEAD,git diff HEADempty. Nodistleg was needed, because the pins import the components relatively fromsrc.predicateProjectionKey, searchFieldsKeydropped from the dependencies:Tests 4 failed | 4 passed (8), the same four rows.predicateProjectionKeydropped:Tests 3 failed | 4 passed (7), the same three rows.Pins (each counts
findcalls)packages/plugin-grid/src/__tests__/ObjectGrid.harvestInputsFetchKey-10689.test.tsx:$select['id','name','industry'].searchableFieldschanged under a term re-reads once, with the new$searchFields.searchableFieldschange with no term.packages/plugin-list/src/__tests__/ListView.harvestInputsFetchKey-10689.test.tsx: the same cases for the list's three inputs, plus the already-keyedsearchableFieldsrow.Verification at head
1842dc0f83pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-list^...' --filter '@object-ui/plugin-grid^...' buildexited 0. Both closures are needed:plugin-list^...alone does not containplugin-grid'splugin-detail,data-objectstackandsdui-parser.pnpm --filter @object-ui/plugin-grid type-checkandpnpm --filter @object-ui/plugin-list type-checkexited 0.tsc -p tsconfig.test.json --listFileslists each new pin file.pnpm exec vitest run packages/plugin-list/:Test Files 110 passed (110),Tests 1208 passed (1208).packages/plugin-grid/ran in two chunks. Its 177 test files were split 88 + 89, and the union was checked against the full list. Results:88 passed (88)/766 passed (766), and89 passed (89)/855 passed (855).check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s).scripts/check-changeset-presence.mjs: 4 source files of 2 released packages, 2 changesets.changeset:check,check:control-bytes,check:action-forward-parity,check:i18n-keys,check:spec-symbols,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inheritandcheck:icon-record-names.pnpm lintrun is CI's):eslint.config.js:eslint --print-configresolves each one.eslint --format jsonover them reported 4 files and 0 errors.ObjectGrid.tsxandListView.tsxcarry the same warning counts as at base.parserOptions.project/projectService), and no rule undereslint-rules/reads the filesystem, so this diff cannot move the verdict on any untouched file.Acceptance notes
ListViewnamesschema.searchableFieldsby identity in its fetch dependencies. A throwaway probe (deleted, never committed) measured it: an equalsearchableFieldsin a new array, under a search term, re-reads (2find). It is not edited here, for two reasons. The ruling says a row that already re-reads on main is pinned, not re-edited. And that effect's own comment records the objectui#4567 ruling that its by-identity dependencies stay, with stabilisation at the producer. No producer was measured rebuilding the array on every render. Carrier: none.Changesets
.changeset/10689-grid-harvest-inputs-refetch.md(@object-ui/plugin-grid: patch).changeset/10689-list-harvest-inputs-refetch.md(@object-ui/plugin-list: patch)Session:
session_0122Knsowci76D2rBWReCzzZ, seatdomain:ui#1, claim comment 5920079312.Generated by Claude Code