From 3a73ebc80fde01e47590304068ecb4c7f8d15a49 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Tue, 10 Mar 2026 22:33:31 +1300 Subject: [PATCH] feat(quick-23): memoize InlineParameterPanel and simplify toggle handlers - Wrap InlineParameterPanel in React.memo - Simplify handleToggleParams in all 5 generate nodes - Use local isParamsExpanded instead of re-querying store - Eliminates O(n) nodes.find() on every toggle click Co-Authored-By: Claude Opus 4.6 --- src/components/nodes/Generate3DNode.tsx | 7 ++----- src/components/nodes/GenerateAudioNode.tsx | 7 ++----- src/components/nodes/GenerateImageNode.tsx | 7 ++----- src/components/nodes/GenerateVideoNode.tsx | 7 ++----- src/components/nodes/InlineParameterPanel.tsx | 7 +++++-- src/components/nodes/LLMGenerateNode.tsx | 7 ++----- 6 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/components/nodes/Generate3DNode.tsx b/src/components/nodes/Generate3DNode.tsx index 99dfa12a..864708e1 100644 --- a/src/components/nodes/Generate3DNode.tsx +++ b/src/components/nodes/Generate3DNode.tsx @@ -95,11 +95,8 @@ export function Generate3DNode({ id, data, selected }: NodeProps { - const nodes = useWorkflowStore.getState().nodes; - const node = nodes.find(n => n.id === id); - const currentExpanded = (node?.data as Generate3DNodeData)?.parametersExpanded ?? true; - updateNodeData(id, { parametersExpanded: !currentExpanded }); - }, [id, updateNodeData]); + updateNodeData(id, { parametersExpanded: !isParamsExpanded }); + }, [id, isParamsExpanded, updateNodeData]); // Track previous status to detect error transitions const prevStatusRef = useRef(nodeData.status); diff --git a/src/components/nodes/GenerateAudioNode.tsx b/src/components/nodes/GenerateAudioNode.tsx index 3d36e09d..f9f9c579 100644 --- a/src/components/nodes/GenerateAudioNode.tsx +++ b/src/components/nodes/GenerateAudioNode.tsx @@ -198,11 +198,8 @@ export function GenerateAudioNode({ id, data, selected }: NodeProps { - const nodes = useWorkflowStore.getState().nodes; - const node = nodes.find(n => n.id === id); - const currentExpanded = (node?.data as GenerateAudioNodeData)?.parametersExpanded ?? true; - updateNodeData(id, { parametersExpanded: !currentExpanded }); - }, [id, updateNodeData]); + updateNodeData(id, { parametersExpanded: !isParamsExpanded }); + }, [id, isParamsExpanded, updateNodeData]); // Dynamic handles based on inputSchema const dynamicHandles = useMemo(() => { diff --git a/src/components/nodes/GenerateImageNode.tsx b/src/components/nodes/GenerateImageNode.tsx index 4309899d..0490e454 100644 --- a/src/components/nodes/GenerateImageNode.tsx +++ b/src/components/nodes/GenerateImageNode.tsx @@ -151,11 +151,8 @@ export function GenerateImageNode({ id, data, selected }: NodeProps { - const nodes = useWorkflowStore.getState().nodes; - const node = nodes.find(n => n.id === id); - const currentExpanded = (node?.data as NanoBananaNodeData)?.parametersExpanded ?? true; - updateNodeData(id, { parametersExpanded: !currentExpanded }); - }, [id, updateNodeData]); + updateNodeData(id, { parametersExpanded: !isParamsExpanded }); + }, [id, isParamsExpanded, updateNodeData]); // Handle provider change const handleProviderChange = useCallback( diff --git a/src/components/nodes/GenerateVideoNode.tsx b/src/components/nodes/GenerateVideoNode.tsx index 3a8c7953..6b52a970 100644 --- a/src/components/nodes/GenerateVideoNode.tsx +++ b/src/components/nodes/GenerateVideoNode.tsx @@ -131,11 +131,8 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps { - const nodes = useWorkflowStore.getState().nodes; - const node = nodes.find(n => n.id === id); - const currentExpanded = (node?.data as GenerateVideoNodeData)?.parametersExpanded ?? true; - updateNodeData(id, { parametersExpanded: !currentExpanded }); - }, [id, updateNodeData]); + updateNodeData(id, { parametersExpanded: !isParamsExpanded }); + }, [id, isParamsExpanded, updateNodeData]); // Handle provider change const handleProviderChange = useCallback( diff --git a/src/components/nodes/InlineParameterPanel.tsx b/src/components/nodes/InlineParameterPanel.tsx index d9f6238b..b26b139d 100644 --- a/src/components/nodes/InlineParameterPanel.tsx +++ b/src/components/nodes/InlineParameterPanel.tsx @@ -1,6 +1,6 @@ "use client"; -import { ReactNode } from "react"; +import React, { ReactNode } from "react"; interface InlineParameterPanelProps { expanded: boolean; @@ -13,7 +13,7 @@ interface InlineParameterPanelProps { * Collapsible parameter container for inline display within generation nodes. * Provides a chevron toggle button and instant expand/collapse. */ -export function InlineParameterPanel({ +function InlineParameterPanelInner({ expanded, onToggle, children, @@ -57,3 +57,6 @@ export function InlineParameterPanel({ ); } + +// Memoized export to prevent unnecessary re-renders +export const InlineParameterPanel = React.memo(InlineParameterPanelInner); diff --git a/src/components/nodes/LLMGenerateNode.tsx b/src/components/nodes/LLMGenerateNode.tsx index f19ab45f..d844ceed 100644 --- a/src/components/nodes/LLMGenerateNode.tsx +++ b/src/components/nodes/LLMGenerateNode.tsx @@ -71,11 +71,8 @@ export function LLMGenerateNode({ id, data, selected }: NodeProps { - const nodes = useWorkflowStore.getState().nodes; - const node = nodes.find(n => n.id === id); - const currentExpanded = (node?.data as LLMGenerateNodeData)?.parametersExpanded ?? true; - updateNodeData(id, { parametersExpanded: !currentExpanded }); - }, [id, updateNodeData]); + updateNodeData(id, { parametersExpanded: !isParamsExpanded }); + }, [id, isParamsExpanded, updateNodeData]); // LLM parameter handlers const handleProviderChange = useCallback(