This is an automated email from the ASF dual-hosted git repository.

dengliming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 8eb1958a fix(SiderMenu): derive flatMenuKeys from current menuData 
(#700)
8eb1958a is described below

commit 8eb1958a3c9a966ff5713260e383d552238ad5dd
Author: Revan0809 <[email protected]>
AuthorDate: Thu Oct 1 13:09:57 2026 +0530

    fix(SiderMenu): derive flatMenuKeys from current menuData (#700)
    
    SiderMenu cached this.flatMenuKeys in the constructor and never
    rebuilt it when the menuData prop changed later (e.g. plugin or
    permission menus that populate asynchronously, or a namespace change
    introducing new routes). getSelectedMenuKeys() kept matching against
    the stale array, so newly-added routes could render but never show as
    selected in the sider.
    
    getDefaultCollapsedSubMenus already recomputed a fresh flat-key array
    from nextProps.menuData for the open-keys calculation in
    getDerivedStateFromProps; getSelectedMenuKeys now does the same by
    deriving flatMenuKeys from this.props.menuData on every call instead
    of reading a cached instance field.
    
    Fixes #642
---
 src/components/SiderMenu/SiderMenu.js       | 13 +++++++++----
 src/components/SiderMenu/SilderMenu.test.js | 28 +++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/src/components/SiderMenu/SiderMenu.js 
b/src/components/SiderMenu/SiderMenu.js
index 54ab0c00..9bcd6619 100644
--- a/src/components/SiderMenu/SiderMenu.js
+++ b/src/components/SiderMenu/SiderMenu.js
@@ -81,9 +81,11 @@ export const getMenuMatchKeys = (flatMenuKeys, paths) =>
 export default class SiderMenu extends PureComponent {
   constructor(props) {
     super(props);
-    this.flatMenuKeys = getFlatMenuKeys(props.menuData);
     this.state = {
-      openKeys: SiderMenu.getDefaultCollapsedSubMenus(props, 
this.flatMenuKeys),
+      openKeys: SiderMenu.getDefaultCollapsedSubMenus(
+        props,
+        getFlatMenuKeys(props.menuData),
+      ),
       localeName: "",
       mode: "inline",
       theme: "dark",
@@ -230,11 +232,14 @@ export default class SiderMenu extends PureComponent {
   // Get the currently selected menu
   getSelectedMenuKeys = () => {
     const {
+      menuData,
       location: { pathname },
     } = this.props;
 
-    // console.log(this.flatMenuKeys, urlToList(pathname));
-    return getMenuMatchKeys(this.flatMenuKeys, urlToList(pathname));
+    // Derive flatMenuKeys from the current menuData on every call instead of
+    // caching it, since menuData can change after construction (e.g. plugin
+    // or permission menus that load asynchronously).
+    return getMenuMatchKeys(getFlatMenuKeys(menuData), urlToList(pathname));
   };
 
   // conversion Path
diff --git a/src/components/SiderMenu/SilderMenu.test.js 
b/src/components/SiderMenu/SilderMenu.test.js
index ac81234f..5e06b2af 100644
--- a/src/components/SiderMenu/SilderMenu.test.js
+++ b/src/components/SiderMenu/SilderMenu.test.js
@@ -16,7 +16,7 @@
  */
 
 import { urlToList } from "../_utils/pathTools";
-import { getFlatMenuKeys, getMenuMatchKeys } from "./SiderMenu";
+import SiderMenu, { getFlatMenuKeys, getMenuMatchKeys } from "./SiderMenu";
 
 const menu = [
   {
@@ -87,3 +87,29 @@ describe("test menu match", () => {
     ).toEqual(["/userinfo", "/userinfo/:id", "/userinfo/:id/info"]);
   });
 });
+
+describe("SiderMenu#getSelectedMenuKeys", () => {
+  it("matches a route added to menuData after construction", () => {
+    // menuData can be populated asynchronously (e.g. plugin or permission
+    // menus that load after the sider mounts), so the instance must derive
+    // its flattened keys from the current menuData rather than a value
+    // cached at construction time.
+    const instance = new SiderMenu({
+      menuData: menu,
+      location: { pathname: "/dashboard" },
+    });
+
+    instance.props = {
+      menuData: [
+        ...menu,
+        { path: "/plugin", children: [{ path: "/plugin/detail" }] },
+      ],
+      location: { pathname: "/plugin/detail" },
+    };
+
+    expect(instance.getSelectedMenuKeys()).toEqual([
+      "/plugin",
+      "/plugin/detail",
+    ]);
+  });
+});

Reply via email to