Skip to content

Commit

Permalink
fix: introduced custom hook with proper error handling for polling
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskari committed Oct 28, 2024
1 parent 2e167aa commit 5659d16
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 8 deletions.
15 changes: 7 additions & 8 deletions src/shared/hooks/BackendAPI/useGet.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { v4 as uuid } from 'uuid';

import { useFetch } from 'shared/hooks/BackendAPI/useFetch';
import { authDataState } from '../../../state/authDataAtom';
import { usePolling } from './usePolling';

// allow <n> consecutive requests to fail before displaying error
const ERROR_TOLERANCY = 2;
Expand Down Expand Up @@ -96,14 +97,12 @@ const useGetHook = processDataFn =>
[fetch, authData],
);

useEffect(() => {
const receivedForbidden = error?.code === 403;

// POLLING
if (!pollingInterval || receivedForbidden || skip) return;
const intervalId = setInterval(refetch(true, data), pollingInterval);
return _ => clearInterval(intervalId);
}, [path, pollingInterval, data, error, skip, refetch]);
usePolling(() => refetch(true, data), {
pollingInterval,
error,
skip,
path,
});

useEffect(() => {
// INITIAL FETCH on path being set/changed
Expand Down
44 changes: 44 additions & 0 deletions src/shared/hooks/BackendAPI/usePolling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useEffect, useCallback, useRef } from 'react';

interface PollingOptions {
pollingInterval?: number;
error?: any;
skip?: boolean;
path?: string;
}

export const usePolling = <T>(
refetchFn: () => Promise<T>,
options: PollingOptions,
) => {
const { pollingInterval = 0, error, skip = false, path } = options;
const intervalIdRef = useRef<NodeJS.Timeout>();

const cleanup = useCallback(() => {
if (intervalIdRef.current) {
clearInterval(intervalIdRef.current);
intervalIdRef.current = undefined;
}
}, []);

const safeRefetch = useCallback(async () => {
try {
await refetchFn();
} catch (error) {
cleanup();
}
}, [refetchFn, cleanup]);

useEffect(() => {
const receivedForbidden = error?.code === 403;
if (!pollingInterval || receivedForbidden || skip) {
cleanup();
return;
}

safeRefetch();
intervalIdRef.current = setInterval(safeRefetch, pollingInterval);

return cleanup;
}, [pollingInterval, error, skip, safeRefetch, cleanup, path]);
};

0 comments on commit 5659d16

Please sign in to comment.