useGeneratedColumns can cache a stale display component lookup
Describe the bug
useGeneratedColumns reads the display component registry inside a useMemo whose dependency list contains nothing registry-related:
}, [fields, customizeColumns, rowActions, deleteMutation, additionalColumns,
defaultColumnOrder, pageId, pageBlock?.blockId]);The registry is a plain Map with no subscription mechanism, so there is nothing that could be added to that list to make the memo recompute when a component registers.
If every prop in the dependency list is referentially stable across renders, a column that generated before a display component was registered keeps the un-registered renderer permanently. Registering later has no effect at all.
This was confirmed with a probe that mounts the hook, renders once with nothing registered, then registers and forces a re-render:
Referentially stable props -> ["core-money-cell", "core-money-cell"] stale, permanently
Inline literal in any dep -> ["core-money-cell", "late-registered"] recoversWhy it is not currently a live bug
Every existing call site passes at least one inline object or array literal, so the memo recomputes on every render and is effectively inert. For example order-table.tsx:168 memoises customizeColumns but passes rowActions: [] inline, and product-variants-table.tsx passes customizeColumns={{...}} inline.
That makes this a latent trap rather than a present defect. The day someone stabilises those props as a performance improvement, display component overrides silently stop working, and nothing will point at the change that caused it.
Background
Before #4064 the registry was read inside the cell renderer, so it could never go stale. #5339 restores the registry-first precedence that #4064 removed, but reads the registry during column generation rather than at cell-render time. That is the one place #5339 does not faithfully restore the earlier semantics, and it was a deliberate trade-off: routing the custom-cell path back through CellWrapper would undo the direct-call property that #4064 introduced to stop cells unmounting on every table re-render.
Possible directions
- Give the display component registry a subscription, so consumers can re-render when it changes.
- Read the registry at cell-render time again, and solve the unmounting problem #4064 addressed some other way.
- Leave the behaviour as it is and document that
useGeneratedColumnscallers must not fully stabilise their props.
Additional context
Raised independently by the contributor on #5339, by a review pass on the same PR, and by the verification that preceded merging it. Three separate readings landing on the same point.
Source: vendurehq/vendure