React simple polling
custom hook
usePollingEffect.
Pablo Garcia
·
Follow
2 min read
29
A remarkably simple polling function can be
implemented with React hooks.
There are two main differences between a
usePollingEffect and a useInterval custom hook. First,
the polling effect must execute as soon as it is called
(contrary to an interval which would trigger the first
call only after the specified time has passed). Second,
we can’t trigger a new call if the previous call hasn’t
finalized, the polling hook must wait until the
previous call was finalized while the interval shouldn’t
care.
function usePollingEffect(
asyncCallback,
dependencies = [],
interval = 10_000 // 10 seconds,
onCleanUp = () => {}
} = {},
) {
const timeoutIdRef = useRef(null)
useEffect(() => {
let _stopped = false
// Side note: preceding semicolon needed for IIFEs.
;(async function pollingCallback() {
try {
await asyncCallback()
} finally {
// Set timeout after it finished, unless stopped
[Link] = !_stopped && setTimeout(
pollingCallback,
interval
)
})()
// Clean up if dependencies change
return () => {
_stopped = true // prevent racing conditions
clearTimeout([Link])
onCleanUp()
}, [...dependencies, interval])
}
This hook tries to execute the async callback. Then it
creates a timeout with the expected interval between
calls. This takes care of immediately calling the
polling function and waiting until the previous call
has finalized before creating a timeout.
Usage
const [data, setData] = useState({})
usePollingEffect(
async () => setData(await fetch(...)),
[],
{ interval: 3000, onCleanUp: () => {...} } // optional
)
onCleanUp is a function executed during the cleanup
phase of useEffect.
We can also use it in conjunction with
useMountedState to prevent the Can’t perform a React
state update on an unmounted component error:
const [data, setData] = useMountedState({})
usePollingEffect(
async () => setData(await fetch(...)),
[],
{ interval: 3000 }
Enhancements
If you are looking into stopping a polling mechanism,
you might also want to cancel a fetch request by
Using AbortController with Fetch API and ReactJS:
import { customFetch, abortRequestSafe } from '...'
const KEY = 'HEALTH_CHECK'
[Link] = () => abortRequestSafe(KEY)
async function healthCheck() {
return await customFetch('/health', { signalKey: KEY })
usePollingEffect(
async () => await healthCheck(),
[],
{ onCleanUp: () => [Link]() }
Furthermore, we could add a mechanism to kill the
poll if we needed it:
function usePollingEffect(...) {
const [dead, kill] = useState(false)
// ...
useEffect(() => {
if(dead) {
return
// ...
}, [..., dead])
return [() => kill(true), () => kill(false)]
const [killPoll, respawnPoll] = usePollingEffect(...)
React
Reactjs
Polling
Hooks
JavaScript