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 });