From 877d1defadbdd010c527bba2bb9dbe1ab63f82ef Mon Sep 17 00:00:00 2001 From: Harri Lehtola Date: Sun, 26 Jan 2025 14:37:12 +0200 Subject: [PATCH] fix: Fix showing selected state in sidebar navigation items in UI Our `useMatchSubpath` hook uses these two react-router-dom hooks: 1. useResolvedPath 2. useMatch After some investigation, I found that useMatch doesn't work with relative or partial paths: https://github.com/remix-run/react-router/issues/8684#issuecomment-1050521422. Furthermore, in our Sidebar useResolvedPath doesn't include any parts of the current page pathname in the result, resulting in just e.g. /data-source, and thus useMatch doesn't return a match. Not sure exactly why this happens, since we get a full resolved path when calling useMatchSubpath in at least RegularFeatureInstance.tsx, but it's probably related to where we render the components in the component tree, and Sidebar is rendered outside the React Router Outlet component. I found out these differences with some console.logs in useMatchSubpath. The fix is to include the full path when calling useMatchSubpath in Sidebar, so that it fully matches the current location used by useMatch. Signed-off-by: Harri Lehtola --- ui/src/pages/Sidebar.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ui/src/pages/Sidebar.tsx b/ui/src/pages/Sidebar.tsx index dac02709ba..fbd1a8cf22 100644 --- a/ui/src/pages/Sidebar.tsx +++ b/ui/src/pages/Sidebar.tsx @@ -55,12 +55,14 @@ const SideNav = () => { : "" }`; + const baseUrl = `${process.env.PUBLIC_URL || ""}/p/${projectName}`; + const sideNav = [ { name: "Home", id: htmlIdGenerator("basicExample")(), onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/`); + navigate(`${baseUrl}/`); }, items: [ { @@ -68,45 +70,45 @@ const SideNav = () => { id: htmlIdGenerator("dataSources")(), icon: , onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/data-source`); + navigate(`${baseUrl}/data-source`); }, - isSelected: useMatchSubpath("data-source"), + isSelected: useMatchSubpath(`${baseUrl}/data-source`), }, { name: entitiesLabel, id: htmlIdGenerator("entities")(), icon: , onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/entity`); + navigate(`${baseUrl}/entity`); }, - isSelected: useMatchSubpath("entity"), + isSelected: useMatchSubpath(`${baseUrl}/entity`), }, { name: featureViewsLabel, id: htmlIdGenerator("featureView")(), icon: , onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/feature-view`); + navigate(`${baseUrl}/feature-view`); }, - isSelected: useMatchSubpath("feature-view"), + isSelected: useMatchSubpath(`${baseUrl}/feature-view`), }, { name: featureServicesLabel, id: htmlIdGenerator("featureService")(), icon: , onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/feature-service`); + navigate(`${baseUrl}/feature-service`); }, - isSelected: useMatchSubpath("feature-service"), + isSelected: useMatchSubpath(`${baseUrl}/feature-service`), }, { name: savedDatasetsLabel, id: htmlIdGenerator("savedDatasets")(), icon: , onClick: () => { - navigate(`${process.env.PUBLIC_URL || ""}/p/${projectName}/data-set`); + navigate(`${baseUrl}/data-set`); }, - isSelected: useMatchSubpath("data-set"), + isSelected: useMatchSubpath(`${baseUrl}/data-set`), }, ], },