Tech Blog - Akihiro Suzuki

setIntervalを便利に使うReact Hooks

December 31, 2021

setInterval を React で便利に使うための useInterval を実装したのでご紹介。

Gist に上げたものが以下。

import { useEffect, useReducer, useRef } from 'react'
type Action = 'start' | 'stop'
type Control = {
start: () => void
stop: () => void
}
type State = 'RUNNING' | 'STOPPED'
type OnUpdate = () => void
type Options = {
interval: number
autostart: boolean
onUpdate?: OnUpdate
}
const reducer = (state: State, action: Action): State => {
switch (action) {
case 'start':
return 'RUNNING'
case 'stop':
return 'STOPPED'
default:
return state
}
}
export const useInterval = ({
interval = 1000,
autostart = true,
onUpdate,
}: Partial<Options>): [State, Control] => {
const onUpdateRef = useRef<OnUpdate>(() => {})
const [state, dispatch] = useReducer(reducer, 'STOPPED')
const start = () => {
dispatch('start')
}
const stop = () => {
dispatch('stop')
}
useEffect(() => {
onUpdateRef.current = onUpdate ?? (() => {})
}, [onUpdate])
useEffect(() => {
if (autostart) {
dispatch('start')
}
}, [autostart])
useEffect(() => {
let timerId: NodeJS.Timeout | undefined = undefined
if (state === 'RUNNING') {
timerId = setInterval(() => {
onUpdateRef.current()
}, interval)
} else {
timerId && clearInterval(timerId)
}
return () => {
timerId && clearInterval(timerId)
}
}, [interval, state])
return [state, { start, stop }]
}
export default useInterval
view raw useInterval.ts hosted with ❤ by GitHub

useEffect の内部で setInterval を呼び、cleanup で clearInterval を呼んでいる。

設定値

オプション 説明
interval 実行間隔[ms]
autostart これをtrueにすると Mount と同時に setInterval が開始される
onUpdate 定期実行される関数。

戻り値

説明
state RUNNING or STOPPED
{start,stop} 定期実行を開始/終了

実装の解説

useInterval の実装については Qiita と Zenn に技術記事を投稿したので、詳しく知りたい方は以下を参照


profile

鈴木 章弘 (Suzuki Akihiro)
バックエンドエンジニア(TypeScript & マイクロサービス)
profile