diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 00000000..e69de29b diff --git a/client/src/QueueEntry.tsx b/client/src/QueueEntry.tsx index 3174a70f..2ab7d7da 100644 --- a/client/src/QueueEntry.tsx +++ b/client/src/QueueEntry.tsx @@ -17,32 +17,38 @@ import * as types from "./types"; import * as utils from "./utils"; import TopButton from "./TopButton"; -export const QueueEntry = (props: { - node_id: types.TNodeId; - index: number; -}) => { - const exists = useRawSelector((state) => - Object.hasOwn(state.data.nodes, props.node_id), - ); - return exists ? ( - <_QueueEntry node_id={props.node_id} index={props.index} /> - ) : ( -
// `null` is not allowed as Virtuoso does not allow 0-height elements. - ); -}; +export const QueueEntry = React.memo( + (props: { node_id: types.TNodeId; index: number }) => { + // ⚡ Bolt: Memoize QueueEntry to prevent unnecessary re-renders of virtualized list items + // when parent components update, significantly reducing React render times during scrolling. + const exists = useRawSelector((state) => + Object.hasOwn(state.data.nodes, props.node_id), + ); + return exists ? ( + <_QueueEntry node_id={props.node_id} index={props.index} /> + ) : ( +
// `null` is not allowed as Virtuoso does not allow 0-height elements. + ); + }, +); +QueueEntry.displayName = "QueueEntry"; -const _QueueEntry = (props: { node_id: types.TNodeId; index: number }) => { - const isTodo = - utils.assertV( - useSelector((state) => state.swapped_nodes.status?.[props.node_id]), - ) === "todo"; +const _QueueEntry = React.memo( + (props: { node_id: types.TNodeId; index: number }) => { + // ⚡ Bolt: Memoize internal _QueueEntry to avoid cascading renders. + const isTodo = + utils.assertV( + useSelector((state) => state.swapped_nodes.status?.[props.node_id]), + ) === "todo"; - return isTodo ? ( - - ) : ( - - ); -}; + return isTodo ? ( + + ) : ( + + ); + }, +); +_QueueEntry.displayName = "_QueueEntry"; const NonTodoQueueEntry = (props: { node_id: types.TNodeId;