feat: improve error handling and manage component mount state in AiProvidersAmpcodeEditPage

This commit is contained in:
LTbinglingfeng
2026-01-30 02:00:35 +08:00
parent 5c85df486e
commit 129d89cf67
2 changed files with 28 additions and 29 deletions

View File

@@ -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({

View File

@@ -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<VertexFormState>(() => 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('');