From d30d64ce93a1eb9f7557215b0838ae9567ead9bb Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Thu, 12 Feb 2026 20:49:47 +0300 Subject: [PATCH] refactor(useFileMentions): implement abort controller for fetch requests --- src/components/chat/hooks/useFileMentions.tsx | 21 ++++++++++++++----- src/utils/api.js | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/chat/hooks/useFileMentions.tsx b/src/components/chat/hooks/useFileMentions.tsx index 1a6d2ab..4445086 100644 --- a/src/components/chat/hooks/useFileMentions.tsx +++ b/src/components/chat/hooks/useFileMentions.tsx @@ -56,15 +56,19 @@ export function useFileMentions({ selectedProject, input, setInput, textareaRef const [atSymbolPosition, setAtSymbolPosition] = useState(-1); useEffect(() => { + const abortController = new AbortController(); + const fetchProjectFiles = async () => { - if (!selectedProject) { - setFileList([]); - setFilteredFiles([]); + const projectName = selectedProject?.name; + setFileList([]); + setFilteredFiles([]); + if (!projectName) { return; } + try { - const response = await api.getFiles(selectedProject.name); + const response = await api.getFiles(projectName, { signal: abortController.signal }); if (!response.ok) { return; } @@ -72,12 +76,19 @@ export function useFileMentions({ selectedProject, input, setInput, textareaRef const files = (await response.json()) as ProjectFileNode[]; setFileList(flattenFileTree(files)); } catch (error) { + // Ignore aborts from rapid project switches; we only care about the latest request. + if ((error as { name?: string })?.name === 'AbortError') { + return; + } console.error('Error fetching files:', error); } }; fetchProjectFiles(); - }, [selectedProject]); + return () => { + abortController.abort(); + }; + }, [selectedProject?.name]); useEffect(() => { const textBeforeCursor = input.slice(0, cursorPosition); diff --git a/src/utils/api.js b/src/utils/api.js index c423875..f680b1d 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -101,8 +101,8 @@ export const api = { method: 'PUT', body: JSON.stringify({ filePath, content }), }), - getFiles: (projectName) => - authenticatedFetch(`/api/projects/${projectName}/files`), + getFiles: (projectName, options = {}) => + authenticatedFetch(`/api/projects/${projectName}/files`, options), transcribe: (formData) => authenticatedFetch('/api/transcribe', { method: 'POST',