LoginSignup
0
0

More than 1 year has passed since last update.

React入門 - Tips5 - 無限レンダリング

Posted at

目次

無限レンダリング

この記事を書くきっかけは、Reactのプロジェクトに入って間もない頃に、もちろんReactスキルも低い状態で試行錯誤していた状況でよく以下のエラーに出会ったということを思い出したというところです。

Error: Too many re-renders. React limits the number ・・・・

ちゃんと学習することで、特にReactフック(特にuseEffect, useLayoutEffect)の第2引数の役割についての理解に繋がるかと思います。


ちなみに、今回codesandboxでは、想定したエラーが出せませんでした。
ですので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

ざっくりと説明すると

  1. ブラウザでアクセスすることによりAppが読み込まれる
  2. useEffectが実行される
  3. 上記useEffect内でstateが変更される
  4. 上記により、再度Appが読み込まれる
  5. useEffectが実行される
  6. 上記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()) );
  }, []);

今回の無限レンダリングは、かなり簡単な例を挙げました。
他にも関数の書き方(アロー関数を使わない)など原因となるコーディングは、いくつかあると思います。
それらに出会ったときに、解決のヒントになれば幸いです。

※また、無限レンダリングのネタ見つけたら追記します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0