From b9e1eb48ad42c82f6289aeee46c5d14b960611b1 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Mon, 3 Nov 2025 19:04:29 -0800 Subject: [PATCH] perf(ui): reduce unnecessary remounting of pillselector --- .../ui/src/elements/PillSelector/index.tsx | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/ui/src/elements/PillSelector/index.tsx b/packages/ui/src/elements/PillSelector/index.tsx index 25b04038f82..3bd5338975c 100644 --- a/packages/ui/src/elements/PillSelector/index.tsx +++ b/packages/ui/src/elements/PillSelector/index.tsx @@ -30,52 +30,53 @@ export type Props = { * If `draggable` is true, the pills can be reordered by dragging. */ export const PillSelector: React.FC = ({ draggable, onClick, pills }) => { - const Wrapper = React.useMemo(() => { - if (draggable) { - return ({ children }) => ( - pill.name)} - onDragEnd={({ moveFromIndex, moveToIndex }) => { - draggable.onDragEnd({ - moveFromIndex, - moveToIndex, - }) + // IMPORTANT: Do NOT wrap DraggableSortable in a dynamic component function using useMemo. + // BAD: useMemo(() => ({ children }) => ..., [deps]) + // This creates a new function reference on each recomputation, causing React to treat it as a + // different component type, triggering unmount/mount cycles instead of just updating props. + // GOOD: Use conditional rendering directly: draggable ? :
+ const pillElements = React.useMemo(() => { + return pills.map((pill, i) => { + return ( + : } + id={pill.name} + key={pill.key ?? `${pill.name}-${i}`} + onClick={() => { + if (onClick) { + void onClick({ pill }) + } }} + size="small" > - {children} - + {pill.Label ?? {pill.name}} + ) - } else { - return ({ children }) =>
{children}
- } - }, [draggable, pills]) + }) + }, [pills, onClick, draggable]) - return ( - - {pills.map((pill, i) => { - return ( - : } - id={pill.name} - key={pill.key ?? `${pill.name}-${i}`} - onClick={() => { - if (onClick) { - void onClick({ pill }) - } - }} - size="small" - > - {pill.Label ?? {pill.name}} - - ) - })} - - ) + if (draggable) { + return ( + pill.name)} + onDragEnd={({ moveFromIndex, moveToIndex }) => { + draggable.onDragEnd({ + moveFromIndex, + moveToIndex, + }) + }} + > + {pillElements} + + ) + } + + return
{pillElements}
}