diff --git a/web/app/ai-chat/page.js b/web/app/ai-chat/page.js index 0cdd6429..fdc43d84 100644 --- a/web/app/ai-chat/page.js +++ b/web/app/ai-chat/page.js @@ -136,6 +136,8 @@ function AiChatPage() { useEffect(() => { if (!token || authLoading) return; + let stale = false; + async function init() { setLoadingConv(true); setError(null); @@ -147,6 +149,7 @@ function AiChatPage() { const res = await fetch(`${API_BASE}/api/v1/chat/conversations`, { headers: { Authorization: `Bearer ${token}` }, }); + if (stale) return; if (res.ok) { const list = await res.json(); const openAi = Array.isArray(list) @@ -155,12 +158,12 @@ function AiChatPage() { if (openAi) convId = openAi.id; } } catch { + if (stale) return; setError("Failed to load conversations."); } } if (!convId) { - // Auto-create a new AI conversation try { const res = await fetch(`${API_BASE}/api/v1/chat/conversations`, { method: "POST", @@ -170,17 +173,19 @@ function AiChatPage() { }, body: JSON.stringify({ message: "Hello! I'd like to chat with the AI assistant." }), }); + if (stale) return; if (res.ok) { const conv = await res.json(); convId = conv.id; } } catch { - // silent + if (stale) return; } } if (!convId) { await fetchConversations(); + if (stale) return; setLoadingConv(false); return; } @@ -190,6 +195,7 @@ function AiChatPage() { fetchMessages(convId), fetchConversations(), ]); + if (stale) return; setLoadingConv(false); startPolling(convId); router.replace(`/ai-chat?id=${convId}`, { scroll: false }); @@ -198,6 +204,7 @@ function AiChatPage() { init(); return () => { + stale = true; if (pollRef.current) clearInterval(pollRef.current); }; }, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling, fetchConversations, router]); diff --git a/web/app/chat/page.js b/web/app/chat/page.js index a566a487..28e71a96 100644 --- a/web/app/chat/page.js +++ b/web/app/chat/page.js @@ -152,6 +152,8 @@ function ChatPage() { useEffect(() => { if (!token || authLoading) return; + let stale = false; + async function init() { setLoadingConv(true); setError(null); @@ -163,6 +165,7 @@ function ChatPage() { const res = await fetch(`${API_BASE}/api/v1/chat/conversations`, { headers: { Authorization: `Bearer ${token}` }, }); + if (stale) return; if (res.ok) { const list = await res.json(); const open = Array.isArray(list) @@ -171,12 +174,14 @@ function ChatPage() { if (open) convId = open.id; } } catch { + if (stale) return; setError("Failed to load conversations."); } } if (!convId) { await fetchConversations(); + if (stale) return; setLoadingConv(false); setConversation(null); return; @@ -187,6 +192,7 @@ function ChatPage() { fetchMessages(convId), fetchConversations(), ]); + if (stale) return; setLoadingConv(false); startPolling(convId); } @@ -194,6 +200,7 @@ function ChatPage() { init(); return () => { + stale = true; if (pollRef.current) clearInterval(pollRef.current); }; }, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling, fetchConversations]);