Created
June 29, 2023 12:34
-
-
Save dctanner/882a71fbb6f15153108cdfdf5f33c545 to your computer and use it in GitHub Desktop.
Reload loader data at interval without throwing error on network failure
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 useRegularFetchWithInterval from "./useRegularFetchWithInterval"; | |
export async function loader() { | |
// Get data | |
return data; | |
} | |
export default function MyRoute() { | |
const loaderData = useLoaderData(); | |
const [liveData] = useRegularFetchWithInterval({ route: `/myroute?_data=routes%2Fmyroute`, intervalMs: 3000, initialData: loaderData }); | |
return ( | |
<>{liveData}</> | |
); | |
} |
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, useRef } from "react"; | |
export default function useInterval(callback: () => void, delay: number) { | |
const savedCallback = useRef<any>(); | |
// Remember the latest callback. | |
useEffect(() => { | |
savedCallback.current = callback; | |
}, [callback]); | |
// Set up the interval. | |
useEffect(() => { | |
function tick() { | |
savedCallback.current(); | |
} | |
if (delay !== null) { | |
let id = setInterval(tick, delay); | |
return () => clearInterval(id); | |
} | |
}, [delay]); | |
} |
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 { useState, useCallback } from "react"; | |
import useInterval from "./useInterval"; | |
// Do fetch() to the route at interval and return a state object of the latest value | |
export default function useRegularFetchWithInterval({ route, intervalMs, enabled = true, skipInitialFetch = false, initialData }: { route: string; intervalMs: number; enabled?: boolean | (() => boolean); skipInitialFetch?: boolean; initialData?: any }) { | |
const [data, setData] = useState<any>(initialData); | |
const [error, setError] = useState<any>(null); | |
const options = { | |
method: "GET", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
} | |
const fetchData = useCallback(() => { | |
// If enabled is a function, call it to determine if we should fetch, or if it's a boolean just use it | |
if (typeof enabled === "function" && !enabled()) return; | |
if (typeof enabled === "boolean" && !enabled) return; | |
fetch(route, options) | |
.then((res) => res.json()) | |
.then((data) => setData(data)) | |
.catch((err) => setError(err)); | |
}, [route, enabled]); | |
useInterval(fetchData, intervalMs); | |
return [data, error, fetchData]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment