From 129d89cf67c8c66f6b5dd31c80c0c66a245c90b2 Mon Sep 17 00:00:00 2001 From: LTbinglingfeng Date: Fri, 30 Jan 2026 02:00:35 +0800 Subject: [PATCH] feat: improve error handling and manage component mount state in AiProvidersAmpcodeEditPage --- src/pages/AiProvidersAmpcodeEditPage.tsx | 51 +++++++++++++----------- src/pages/AiProvidersVertexEditPage.tsx | 6 +-- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/pages/AiProvidersAmpcodeEditPage.tsx b/src/pages/AiProvidersAmpcodeEditPage.tsx index f436c90..e50b5b3 100644 --- a/src/pages/AiProvidersAmpcodeEditPage.tsx +++ b/src/pages/AiProvidersAmpcodeEditPage.tsx @@ -17,6 +17,12 @@ import type { AmpcodeFormState } from '@/components/providers'; type LocationState = { fromAiProviders?: boolean } | null; +const getErrorMessage = (err: unknown) => { + if (err instanceof Error) return err.message; + if (typeof err === 'string') return err; + return ''; +}; + export function AiProvidersAmpcodeEditPage() { const { t } = useTranslation(); const navigate = useNavigate(); @@ -36,15 +42,10 @@ export function AiProvidersAmpcodeEditPage() { const [error, setError] = useState(''); const [saving, setSaving] = useState(false); const initializedRef = useRef(false); + const mountedRef = useRef(false); const title = useMemo(() => t('ai_providers.ampcode_modal_title'), [t]); - const getErrorMessage = (err: unknown) => { - if (err instanceof Error) return err.message; - if (typeof err === 'string') return err; - return ''; - }; - const handleBack = useCallback(() => { const state = location.state as LocationState; if (state?.fromAiProviders) { @@ -66,6 +67,13 @@ export function AiProvidersAmpcodeEditPage() { return () => window.removeEventListener('keydown', handleKeyDown); }, [handleBack]); + useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + }; + }, []); + useEffect(() => { if (initializedRef.current) return; initializedRef.current = true; @@ -74,31 +82,26 @@ export function AiProvidersAmpcodeEditPage() { setLoaded(false); setMappingsDirty(false); setError(''); - setForm(buildAmpcodeFormState(config?.ampcode ?? null)); + setForm(buildAmpcodeFormState(useConfigStore.getState().config?.ampcode ?? null)); + + void (async () => { + try { + const ampcode = await ampcodeApi.getAmpcode(); + if (!mountedRef.current) return; - let cancelled = false; - ampcodeApi - .getAmpcode() - .then((ampcode) => { - if (cancelled) return; setLoaded(true); updateConfigValue('ampcode', ampcode); clearCache('ampcode'); setForm(buildAmpcodeFormState(ampcode)); - }) - .catch((err: unknown) => { - if (cancelled) return; + } catch (err: unknown) { + if (!mountedRef.current) return; setError(getErrorMessage(err) || t('notification.refresh_failed')); - }) - .finally(() => { - if (cancelled) return; + } finally { + if (!mountedRef.current) return; setLoading(false); - }); - - return () => { - cancelled = true; - }; - }, [clearCache, config?.ampcode, t, updateConfigValue]); + } + })(); + }, [clearCache, t, updateConfigValue]); const clearAmpcodeUpstreamApiKey = async () => { showConfirmation({ diff --git a/src/pages/AiProvidersVertexEditPage.tsx b/src/pages/AiProvidersVertexEditPage.tsx index e38f301..9f46621 100644 --- a/src/pages/AiProvidersVertexEditPage.tsx +++ b/src/pages/AiProvidersVertexEditPage.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Card } from '@/components/ui/Card'; @@ -51,7 +51,6 @@ export function AiProvidersVertexEditPage() { const [saving, setSaving] = useState(false); const [error, setError] = useState(''); const [form, setForm] = useState(() => buildEmptyForm()); - const initializedRef = useRef(false); const hasIndexParam = typeof params.index === 'string'; const editIndex = useMemo(() => parseIndexParam(params.index), [params.index]); @@ -89,9 +88,6 @@ export function AiProvidersVertexEditPage() { }, [handleBack]); useEffect(() => { - if (initializedRef.current) return; - initializedRef.current = true; - let cancelled = false; setLoading(true); setError('');