From 710b6f99b5a5368f50df248b3920eb22f62dfdce Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Tue, 6 May 2025 11:11:47 -0500 Subject: [PATCH] refactor: Reduce Sidebar Rerenders (#7699) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * menubar and hook optimizations * sidebar optimizations * [autofix.ci] apply automated fixes * cleanup * [autofix.ci] apply automated fixes * sidebare button optimization * 🐛 (typescript_test.yml): increase the maximum shard count to 40 to improve test distribution and performance * Get state on focus instead of on keypress * revert test shard change * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: cristhianzl --- .../components/FlowMenu/index.tsx | 35 +++---- src/frontend/src/components/ui/sidebar.tsx | 55 ++++++----- .../src/hooks/flows/use-delete-flow.ts | 2 +- src/frontend/src/hooks/flows/use-save-flow.ts | 18 ++-- .../components/PageComponent/index.tsx | 16 ++-- .../components/bundleItems/index.tsx | 93 ++++++++++--------- .../components/categoryDisclouse/index.tsx | 26 ++---- .../components/categoryGroup/index.tsx | 4 +- .../components/sidebarBundles/index.tsx | 16 +--- .../components/sidebarItemsList/index.tsx | 72 ++++++++++++-- .../components/flowSidebarComponent/index.tsx | 39 ++------ .../flowSidebarComponent/types/index.ts | 18 +--- 12 files changed, 208 insertions(+), 186 deletions(-) diff --git a/src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/index.tsx b/src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/index.tsx index 6745d4d86..04241a8b1 100644 --- a/src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/index.tsx +++ b/src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/index.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate"; import useAddFlow from "@/hooks/flows/use-add-flow"; @@ -35,7 +35,7 @@ import { cn, getNumberFromString } from "@/utils/utils"; import { useQueryClient } from "@tanstack/react-query"; import { useShallow } from "zustand/react/shallow"; -export const MenuBar = ({}: {}): JSX.Element => { +export const MenuBar = memo((): JSX.Element => { const shortcuts = useShortcutsStore((state) => state.shortcuts); const addFlow = useAddFlow(); const setErrorData = useAlertStore((state) => state.setErrorData); @@ -81,20 +81,10 @@ export const MenuBar = ({}: {}): JSX.Element => { const [inputWidth, setInputWidth] = useState(0); const measureRef = useRef(null); const changesNotSaved = useUnsavedChanges(); + const [flowNames, setFlowNames] = useState([]); const { data: folders, isFetched: isFoldersFetched } = useGetFoldersQuery(); const flows = useFlowsManagerStore((state) => state.flows); - const [nameLists, setNameList] = useState([]); - - useEffect(() => { - if (flows) { - const tempNameList: string[] = []; - flows.forEach((flow) => { - tempNameList.push(flow.name); - }); - setNameList(tempNameList.filter((name) => name !== currentFlowName)); - } - }, [flows, currentFlowName]); useGetRefreshFlowsQuery( { @@ -162,17 +152,11 @@ export const MenuBar = ({}: {}): JSX.Element => { const handleEditName = useCallback( (e: React.ChangeEvent) => { const { value } = e.target; - let invalid = false; - for (let i = 0; i < nameLists.length; i++) { - if (value === nameLists[i]) { - invalid = true; - break; - } - } + const invalid = flowNames.includes(value); setIsInvalidName(invalid); setFlowName(value); }, - [nameLists], + [flowNames], ); const handleKeyDown = useCallback( @@ -195,7 +179,6 @@ export const MenuBar = ({}: {}): JSX.Element => { flowName !== currentFlowName && !isInvalidName ) { - // Get a one-time snapshot of currentFlow using get() const currentFlowSnapshot = useFlowStore.getState().currentFlow; const newFlow = { @@ -327,6 +310,12 @@ export const MenuBar = ({}: {}): JSX.Element => { onFocus={() => { setEditingName(true); setFlowName(currentFlowName); + const flows = useFlowsManagerStore.getState().flows; + setFlowNames( + flows + ?.map((flow) => flow.name) + .filter((name) => name !== currentFlowName) ?? [], + ); }} onBlur={handleNameSubmit} value={flowName} @@ -578,6 +567,6 @@ export const MenuBar = ({}: {}): JSX.Element => { ) : ( <> ); -}; +}); export default MenuBar; diff --git a/src/frontend/src/components/ui/sidebar.tsx b/src/frontend/src/components/ui/sidebar.tsx index 1ea333ed9..a2a1eab30 100644 --- a/src/frontend/src/components/ui/sidebar.tsx +++ b/src/frontend/src/components/ui/sidebar.tsx @@ -85,8 +85,8 @@ const SidebarProvider = React.forwardRef< // Helper to toggle the sidebar. const toggleSidebar = React.useCallback(() => { - return setOpen((open) => !open); - }, [setOpen, open]); + return setOpen((prev) => !prev); + }, [setOpen]); // We add a state so that we can do data-state="expanded" or "collapsed". // This makes it easier to style the sidebar with Tailwind classes. @@ -275,6 +275,14 @@ const SidebarTrigger = React.forwardRef< >(({ className, onClick, ...props }, ref) => { const { toggleSidebar } = useSidebar(); + const handleClick = React.useCallback( + (event: React.MouseEvent) => { + onClick?.(event); + toggleSidebar(); + }, + [onClick, toggleSidebar], + ); + return (