目次
無限レンダリング
この記事を書くきっかけは、Reactのプロジェクトに入って間もない頃に、もちろんReactスキルも低い状態で試行錯誤していた状況でよく以下のエラーに出会ったということを思い出したというところです。
Error: Too many re-renders. React limits the number ・・・・
ちゃんと学習することで、特にReactフック(特にuseEffect, useLayoutEffect)の第2引数の役割についての理解に繋がるかと思います。
ちなみに、今回[codesandbox](https://codesandbox.io/)では、想定したエラーが出せませんでした。 ですのでReact実行環境を作成し試してください。 # 無限レンダリングを起こすコーディングまずは、起こさないコーディング
import React, { useState, useEffect } from 'react';
const App = () => {
console.log('App');
const [time, setTime] = useState('');
useEffect(() => {
console.log('useEffect');
setTime('あああ');
});
return <h1>ミリ秒:{time}</h1>
}
export default App;
実行し、コンソールログを確認すると
App
useEffect
App
useEffect
App
ざっくりと説明すると
- ブラウザでアクセスすることにより
App
が読み込まれる - useEffectが実行される
- 上記useEffect内でstateが変更される
- 上記により、再度
App
が読み込まれる - useEffectが実行される
- 上記useEffect内でstateが変更されるるが、stateの内容に変化が無いので終わり
※ちなみに、stateの値がプリミティブ型でなくオブジェクトの場合、たぶん無限レンダリングが起きます。オブジェクト型は中の値でなく参照で比較されるので。。
エラーを起こしてみましょう。
一部分を修正します。
// setTime('あああ');
setTime( String((new Date()).getTime()) );
また、実行後、コンソールログを確認してみてください。
(見た目もずっと更新されていますので、分かるかと思いますが。。。。)
先ほどの説明の6.の6. 上記useEffect内でstateが変更されるるが、stateの内容に変化が無いので終わり
が6. 上記useEffect内でstateが変更され、stateの内容に変化があり終わらない
って感じでしょうか。
初期表示時にミリ秒を表示するだけなら、useEffectの第2引数を[]
にします。
useEffect(() => {
console.log('useEffect');
// setTime('あああ');
setTime( String((new Date()).getTime()) );
}, []);
今回の無限レンダリングは、かなり簡単な例を挙げました。
他にも関数の書き方(アロー関数を使わない)など原因となるコーディングは、いくつかあると思います。
それらに出会ったときに、解決のヒントになれば幸いです。
※また、無限レンダリングのネタ見つけたら追記します。