guard stale init effects

This commit is contained in:
2026-04-16 07:56:57 -06:00
parent 7b4874b8b1
commit 2c9dedb65e
2 changed files with 16 additions and 2 deletions

View File

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

View File

@@ -152,6 +152,8 @@ function ChatPage() {
useEffect(() => { useEffect(() => {
if (!token || authLoading) return; if (!token || authLoading) return;
let stale = false;
async function init() { async function init() {
setLoadingConv(true); setLoadingConv(true);
setError(null); setError(null);
@@ -163,6 +165,7 @@ function ChatPage() {
const res = await fetch(`${API_BASE}/api/v1/chat/conversations`, { const res = await fetch(`${API_BASE}/api/v1/chat/conversations`, {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
}); });
if (stale) return;
if (res.ok) { if (res.ok) {
const list = await res.json(); const list = await res.json();
const open = Array.isArray(list) const open = Array.isArray(list)
@@ -171,12 +174,14 @@ function ChatPage() {
if (open) convId = open.id; if (open) convId = open.id;
} }
} catch { } catch {
if (stale) return;
setError("Failed to load conversations."); setError("Failed to load conversations.");
} }
} }
if (!convId) { if (!convId) {
await fetchConversations(); await fetchConversations();
if (stale) return;
setLoadingConv(false); setLoadingConv(false);
setConversation(null); setConversation(null);
return; return;
@@ -187,6 +192,7 @@ function ChatPage() {
fetchMessages(convId), fetchMessages(convId),
fetchConversations(), fetchConversations(),
]); ]);
if (stale) return;
setLoadingConv(false); setLoadingConv(false);
startPolling(convId); startPolling(convId);
} }
@@ -194,6 +200,7 @@ function ChatPage() {
init(); init();
return () => { return () => {
stale = true;
if (pollRef.current) clearInterval(pollRef.current); if (pollRef.current) clearInterval(pollRef.current);
}; };
}, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling, fetchConversations]); }, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling, fetchConversations]);