Last active
March 8, 2023 00:08
-
-
Save mfunkie/1c9cd6571dbb15d2328381469d218ba1 to your computer and use it in GitHub Desktop.
useRevalidateInterval
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]); | |
} |
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
Summary
useRevalidateInterval
is a hook intended for use with react-router-dom.revalidator.revalidate()
on a specified interval based on the presence of revalidation search param.The value of
1
for the search param value, the default interval, and comments about Apollo are arbitrary.Use case
For lists of elements, I sometimes have a pending status while additional work is being done on an item on that list. This is typically not long-lived. My loaders query data from Apollo Client, and need to be informed of when to use
network-only
as afetchPolicy
. With this hook, I can check for the presence of a pending item in my loader resultant list data, pass to this hook, and be assured that the list will refresh until the item is no longer pending (presumingfetchPolicy
implementation inside loader