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 74f3cb4a fix(aiproxy): declare ApiKeys handlers before useMemo to 
avoid stale closures (#706)
74f3cb4a is described below

commit 74f3cb4a910c124be4fc7b592113adeeb91dbabe
Author: Hussnain Ahmad <[email protected]>
AuthorDate: Sat Oct 10 12:59:35 2026 -0400

    fix(aiproxy): declare ApiKeys handlers before useMemo to avoid stale 
closures (#706)
    
    The columns useMemo referenced onToggle in its dependency array before the
    const declaration was evaluated, so after transpilation the dep was always
    undefined and the memoized renderers kept the first render's page, pageSize,
    queryKey and selectorId. Toggling Enabled after changing page/filter 
refetched
    with stale parameters while the pager showed the new ones.
    
    Declare fetchList, onToggle and onBatchDelete before the memo with 
useCallback
    and complete dependency arrays, and include onBatchDelete in the columns 
deps.
    
    Closes #607
---
 src/routes/Plugin/AiProxy/ApiKeys/index.js | 69 +++++++++++++++++-------------
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/src/routes/Plugin/AiProxy/ApiKeys/index.js 
b/src/routes/Plugin/AiProxy/ApiKeys/index.js
index 2fe2b520..56828455 100644
--- a/src/routes/Plugin/AiProxy/ApiKeys/index.js
+++ b/src/routes/Plugin/AiProxy/ApiKeys/index.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import React, { useEffect, useMemo, useState } from "react";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
 import { connect } from "dva";
 import {
   Button,
@@ -213,6 +213,44 @@ function ApiKeysPage({
     // eslint-disable-next-line
   }, [selectorId, namespaceId]);
 
+  // Declared before `columns` so the memoized renderers always capture the
+  // latest page/filter/selector state instead of stale first-render values.
+  const fetchList = useCallback(
+    async (p = page, ps = pageSize) => {
+      if (!selectorId) return;
+      const res = await getAiProxyApiKeys({
+        selectorId,
+        namespaceId,
+        currentPage: p,
+        pageSize: ps,
+        proxyApiKey:
+          queryKey && queryKey.trim() !== "" ? queryKey.trim() : undefined,
+      });
+      const list = res?.data?.dataList || [];
+      setData(list);
+      setTotal(res?.data?.totalCount || 0);
+    },
+    [selectorId, namespaceId, page, pageSize, queryKey],
+  );
+
+  const onToggle = useCallback(
+    async (ids, enabled) => {
+      if (!selectorId) return;
+      await batchEnableAiProxyApiKeys({ selectorId, ids, enabled });
+      fetchList();
+    },
+    [selectorId, fetchList],
+  );
+
+  const onBatchDelete = useCallback(
+    async (ids) => {
+      if (!selectorId) return;
+      await batchDeleteAiProxyApiKeys({ selectorId, ids });
+      fetchList();
+    },
+    [selectorId, fetchList],
+  );
+
   const columns = useMemo(
     () => [
       { title: "proxyApiKey", dataIndex: "proxyApiKey", key: "proxyApiKey" },
@@ -272,36 +310,9 @@ function ApiKeysPage({
         ),
       },
     ],
-    [namespaceId, onToggle],
+    [namespaceId, onToggle, onBatchDelete],
   );
 
-  const fetchList = async (p = page, ps = pageSize) => {
-    if (!selectorId) return;
-    const res = await getAiProxyApiKeys({
-      selectorId,
-      namespaceId,
-      currentPage: p,
-      pageSize: ps,
-      proxyApiKey:
-        queryKey && queryKey.trim() !== "" ? queryKey.trim() : undefined,
-    });
-    const list = res?.data?.dataList || [];
-    setData(list);
-    setTotal(res?.data?.totalCount || 0);
-  };
-
-  const onToggle = async (ids, enabled) => {
-    if (!selectorId) return;
-    await batchEnableAiProxyApiKeys({ selectorId, ids, enabled });
-    fetchList();
-  };
-
-  const onBatchDelete = async (ids) => {
-    if (!selectorId) return;
-    await batchDeleteAiProxyApiKeys({ selectorId, ids });
-    fetchList();
-  };
-
   const onCreate = async (values) => {
     if (!selectorId) return;
     const res = await addAiProxyApiKey({ selectorId, ...values });

Reply via email to