Next.jsで一定間隔で更新イベントを起こす方法

#Next.js
#useEffect
#定時更新
#setInterval

Nextjsで1分間隔でAPIを叩きデータを更新するポーリング処理を作りたい場合、いくつか方法はあるかと思いますが、今回useEffectとsetIntervalを使って実装してみました。

 

Nextjsは触り始めて間もないので突っ込みどころ多いかもしれませんがご容赦ください、、

pages/ └ dateTimeNow.tsx
import { useEffect, useState } from 'react'; const DateTimeNow: React.FC = () => { const [unixNow, setUnixNow] = useState(new Date().getTime()); useEffect(() => { const intervalMs = 1000 * 5; const intervalId = setInterval(() => { setUnixNow(new Date().getTime()); }, intervalMs); return () => clearInterval(intervalId); }, []); const dateTime = new Date(unixNow) return ( <> 現在時刻: {dateTime.toString()} </> ); }; export default DateTimeNow;

useStateで更新時刻のtimestampを格納する変数unixNowを定義し、useEffect内で最新時刻へsetUnixNow()で更新しています。

useEffect内ではsetIntervalを用いてitervalMsで定義した値分一定間隔でsetUnixNowを発火させます。

なお、useEffectの第二引数に[]をつけないとsetUnixTimeが実行されることでclearIntervalまで実行されてしまうのでご注意ください

APIを叩きたい場合は、setUnixNowの部分をfetch処理に置き換えるか、unixNow自体をuseEffectの第二引数に入れてuseEffectを発火させればよいと思います。

useEffect(() => { // ここにAPIリクエスト処理 }, [unixNow])

http://localhost:3000/dateTimeNow

をブラウザで入力、

以下のように表示され、5秒ごとに更新がかかるようになりました

現在時刻: Sun May 01 2022 17:45:18 GMT+0900 (日本標準時)

現在時刻: Sun May 01 2022 17:45:23 GMT+0900 (日本標準時)

現在時刻: Sun May 01 2022 17:45:28 GMT+0900 (日本標準時)

logをつけて挙動を確認します

import { useEffect, useState } from 'react'; const DateTimeNow: React.FC = () => { const [unixNow, setUnixNow] = useState(new Date().getTime()); useEffect(() => { const intervalMs = 1000 * 5; let count = 0 const intervalId = setInterval(() => { count += 1 console.log('count', count) console.log('setInterval!') setUnixNow(new Date().getTime()); console.log('setInterval after!') }, intervalMs); return () => { console.log('clearInterval!') clearInterval(intervalId) }; }, []); const dateTime = new Date(unixNow) return ( <> 現在時刻: {dateTime.toString()} </> ); }; export default DateTimeNow;

結果は、

count 1 setInterval! setInterval after! count 2 setInterval! setInterval after! count 3 setInterval! setInterval after! count 4 setInterval! setInterval after!

countが期待通りインクリメントされ、clearIntervalは呼ばれずsetInterval内で処理が動き続けました。なお、他ページへ遷移する際にclearIntervalが呼ばれました。

 

次に、useEffectの第二引数を抜いてみました。

import { useEffect, useState } from 'react'; const DateTimeNow: React.FC = () => { const [unixNow, setUnixNow] = useState(new Date().getTime()); useEffect(() => { const intervalMs = 1000 * 5; let count = 0 const intervalId = setInterval(() => { count += 1 console.log('count', count) console.log('setInterval!') setUnixNow(new Date().getTime()); console.log('setInterval after!') }, intervalMs); return () => { console.log('clearInterval!') clearInterval(intervalId) }; }); const dateTime = new Date(unixNow) return ( <> 現在時刻: {dateTime.toString()} </> ); }; export default DateTimeNow;

結果は、

count 1 setInterval after! clearInterval! setInterval! count 1 setInterval after! clearInterval! setInterval! count 1 setInterval after! clearInterval!

のように出力され、countは永遠と1のままで、毎回clearIntervalまで呼ばれてしまいました。

 

useEffectの第二引数を設定しないと、何かしらのuseStateのsetが動くたびの再renderで反応してしまうようです。