Skip to content

Instantly share code, notes, and snippets.

@mfunkie
Last active March 8, 2023 00:08
Show Gist options
  • Save mfunkie/1c9cd6571dbb15d2328381469d218ba1 to your computer and use it in GitHub Desktop.
Save mfunkie/1c9cd6571dbb15d2328381469d218ba1 to your computer and use it in GitHub Desktop.
useRevalidateInterval
import { useEffect } from 'react';
import { useRevalidator, useSearchParams } from 'react-router-dom';
export function useRevalidateInterval(
shouldRevalidate: boolean,
revalidateSearchParam: string,
intervalTimeoutMs = 3000
) {
const [searchParams, setSearchParams] = useSearchParams();
const revalidator = useRevalidator();
const urlIndicatesRevalidate = Boolean(
searchParams.get(revalidateSearchParam)
);
useEffect(() => {
if (shouldRevalidate && !urlIndicatesRevalidate) {
setSearchParams((previousSearchParams) => {
// Preserve existing search parameters
const newSearchParams = new URLSearchParams(previousSearchParams);
newSearchParams.set(revalidateSearchParam, '1');
return newSearchParams;
});
} else if (!shouldRevalidate && urlIndicatesRevalidate) {
setSearchParams((previousSearchParams) => {
// Preserve existing search parameters
const newSearchParams = new URLSearchParams(previousSearchParams);
newSearchParams.delete(revalidateSearchParam);
return newSearchParams;
});
}
}, [
shouldRevalidate,
setSearchParams,
urlIndicatesRevalidate,
revalidateSearchParam
]);
useEffect(() => {
if (urlIndicatesRevalidate) {
// Trigger revalidator on an interval
// It is up to the implementer to use the same `urlSearchParameter`
// and if set, ensure a `network-only` fetchPolicy for any Apollo Queries
const intervalId = setInterval(() => {
// We may miss a tick in the interval but it is better
// than triggering revalidation while the query is still loading
if (revalidator.state !== 'loading') {
revalidator.revalidate();
}
}, intervalTimeoutMs);
return () => {
clearInterval(intervalId);
};
}
}, [revalidator, urlIndicatesRevalidate, intervalTimeoutMs]);
}
@mfunkie
Copy link
Author

mfunkie commented Mar 8, 2023

Implementation in loader may look something like:

const url = new URL(request.url);
const shouldRefetch = Boolean(url.searchParams.get('myRevalidateSearchParam'));

const result = await client.query<Query, Variables>({
  query: LIST_QUERY,
  variables: { listId },
  fetchPolicy: shouldRefetch ? 'network-only' : 'cache-first'
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment