ReactのuserEffectでsetIntervalした時の、インターバルが無限に定義される問題に対処する
はじめに
React上でsetIntervalを使うとき、そのsetIntervalの処理が副作用を生む場合、無限ループに陥ることがあります。
本稿では、その対処法について紹介します。
環境/前提
- 上記ライブラリがインストールされていること。
使用ブラウザ:Chrome
実装
無限ループに陥るコード
React.useEffect(() => {
// インターバルを作成
window.setInterval(() => {
hasSideEffectFunction();
}, 5000);
}, [someState]);
React.useEffect(() => {
// インターバルを作成
window.setInterval(() => {
hasSideEffectFunction();
}, 5000);
}, [someState]);
上記のコードでは、hasSideEffectFunction()
が副作用を引き起こし、実行されるたびにレンダーされます。
さらにレンダーされる度に、setInterval()が実行され、インターバルが無限に増えていきます。
解決策
// インターバルIDを保持する為のref変数(レンダーされても値を保持する)
const intervalNo = React.useRef(0);
React.useEffect(() => {
// インターバルが作成されていない時のみ、setInterval()する
if (intervalNo.current == 0) {
// インターバルを作成
intervalNo.current = window.setInterval(() => {
hasSideEffectFunction();
}, 5000);
}
}, [someState]);
上記のように、setInterval()の返り値を、useRefを使って保持することで、レンダーされるたびにインターバルが作成されるのを防ぐことができます。
これでレンダーを通してインターバルを1つに保つことはできました。
しかし、画面遷移などのコンポーネントの呼び出しをされると、useRefが再び0に定義され、インターバルが作成されてしまいます。
for (let i = 1; i < 1000; i++) window.clearInterval(i);
その対策として、setInterval()を実行する前に、上記のコードにより、定義されているであろうインターバルをfor分で回して削除するようにしてます。
これで画面遷移を通してもインターバルを1つに保つことができます。
(正直無理やり対応してる感が否めないので、定義済みのインターバルを取得できるような知見がある方がいたら教えてほしいです。。。)
Author And Source
この問題について(ReactのuserEffectでsetIntervalした時の、インターバルが無限に定義される問題に対処する), 我々は、より多くの情報をここで見つけました https://qiita.com/Annoske/items/9e977ae3286b5db4b828著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .