mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-24 16:26:32 +02:00
fix(hooks): add AbortController to properly cancel fetch requests on unmount
This commit is contained in:
parent
0cd2b8164d
commit
8a8e5fcd76
4 changed files with 34 additions and 24 deletions
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "SurfSense",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
|
|
@ -34,9 +34,12 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
|||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
// Fetch webhook info
|
||||
// Fetch webhook info
|
||||
useEffect(() => {
|
||||
const fetchWebhookInfo = async () => {
|
||||
const controller = new AbortController();
|
||||
|
||||
const doFetch = async () => {
|
||||
if (!connector.search_space_id) return;
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL;
|
||||
|
|
@ -49,8 +52,11 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
|||
setIsLoading(true);
|
||||
try {
|
||||
const response = await authenticatedFetch(
|
||||
`${baseUrl}/api/v1/webhooks/circleback/${connector.search_space_id}/info`
|
||||
`${baseUrl}/api/v1/webhooks/circleback/${connector.search_space_id}/info`,
|
||||
{ signal: controller.signal }
|
||||
);
|
||||
if (controller.signal.aborted) return;
|
||||
|
||||
if (response.ok) {
|
||||
const data: unknown = await response.json();
|
||||
// Runtime validation with zod schema
|
||||
|
|
@ -59,16 +65,18 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
|||
setWebhookUrl(validatedData.webhook_url);
|
||||
}
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) return;
|
||||
console.error("Failed to fetch webhook info:", error);
|
||||
// Reset state on error
|
||||
setWebhookInfo(null);
|
||||
setWebhookUrl("");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
if (!controller.signal.aborted) setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchWebhookInfo();
|
||||
doFetch().catch(() => {});
|
||||
return () => controller.abort();
|
||||
}, [connector.search_space_id]);
|
||||
|
||||
const handleNameChange = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export function EditorPanelContent({
|
|||
const [displayTitle, setDisplayTitle] = useState(title || "Untitled");
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const controller = new AbortController();
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
setEditorDoc(null);
|
||||
|
|
@ -78,7 +78,7 @@ export function EditorPanelContent({
|
|||
initialLoadDone.current = false;
|
||||
changeCountRef.current = 0;
|
||||
|
||||
const fetchContent = async () => {
|
||||
const doFetch = async () => {
|
||||
const token = getBearerToken();
|
||||
if (!token) {
|
||||
redirectToLogin();
|
||||
|
|
@ -88,10 +88,10 @@ export function EditorPanelContent({
|
|||
try {
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/documents/${documentId}/editor-content`,
|
||||
{ method: "GET" }
|
||||
{ method: "GET", signal: controller.signal }
|
||||
);
|
||||
|
||||
if (cancelled) return;
|
||||
if (controller.signal.aborted) return;
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response
|
||||
|
|
@ -115,18 +115,16 @@ export function EditorPanelContent({
|
|||
setEditorDoc(data);
|
||||
initialLoadDone.current = true;
|
||||
} catch (err) {
|
||||
if (cancelled) return;
|
||||
if (controller.signal.aborted) return;
|
||||
console.error("Error fetching document:", err);
|
||||
setError(err instanceof Error ? err.message : "Failed to fetch document");
|
||||
} finally {
|
||||
if (!cancelled) setIsLoading(false);
|
||||
if (!controller.signal.aborted) setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchContent();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
doFetch().catch(() => {});
|
||||
return () => controller.abort();
|
||||
}, [documentId, searchSpaceId, title]);
|
||||
|
||||
const handleMarkdownChange = useCallback((md: string) => {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export function DocumentTabContent({ documentId, searchSpaceId, title }: Documen
|
|||
const changeCountRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const controller = new AbortController();
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
setDoc(null);
|
||||
|
|
@ -64,7 +64,7 @@ export function DocumentTabContent({ documentId, searchSpaceId, title }: Documen
|
|||
initialLoadDone.current = false;
|
||||
changeCountRef.current = 0;
|
||||
|
||||
const fetchContent = async () => {
|
||||
const doFetch = async () => {
|
||||
const token = getBearerToken();
|
||||
if (!token) {
|
||||
redirectToLogin();
|
||||
|
|
@ -74,10 +74,10 @@ export function DocumentTabContent({ documentId, searchSpaceId, title }: Documen
|
|||
try {
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/documents/${documentId}/editor-content`,
|
||||
{ method: "GET" }
|
||||
{ method: "GET", signal: controller.signal }
|
||||
);
|
||||
|
||||
if (cancelled) return;
|
||||
if (controller.signal.aborted) return;
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response
|
||||
|
|
@ -98,18 +98,16 @@ export function DocumentTabContent({ documentId, searchSpaceId, title }: Documen
|
|||
setDoc(data);
|
||||
initialLoadDone.current = true;
|
||||
} catch (err) {
|
||||
if (cancelled) return;
|
||||
if (controller.signal.aborted) return;
|
||||
console.error("Error fetching document:", err);
|
||||
setError(err instanceof Error ? err.message : "Failed to fetch document");
|
||||
} finally {
|
||||
if (!cancelled) setIsLoading(false);
|
||||
if (!controller.signal.aborted) setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchContent();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
doFetch().catch(() => {});
|
||||
return () => controller.abort();
|
||||
}, [documentId, searchSpaceId]);
|
||||
|
||||
const handleMarkdownChange = useCallback((md: string) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue