無限ループの回避
onChangeイベントでの無限ループ
onChangeイベントでuseState()を使いたい時に、下記のようにすると無限ループになる。
import React, {useState} from "react";
export const Hoge= () =>{
  const [count,setCount] = useState(0);
  const handleButton= () =>  {
    setCount(count+1)
  }
  return(
    <div>
      <div>Count: {count}</div>
      <button onClick={handleButton()}>Button</button>
    </div>
  );
}
エラーは下記の通り。
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
翻訳すると、「再レンダリングが多すぎます。 React は、無限ループを防ぐためにレンダリングの数を制限します。」
正しくは、下記のようにアロー関数を使うと無限ループを避けられる。
import React, {useState} from "react";
export const Hoge= () =>{
  const [count,setCount] = useState(0);
  const handleButton= () =>  {
    setCount(count+1)
  }
  return(
    <div>
      <div>Count: {count}</div>
      <button onClick={() => handleButton()}>Button</button>
    </div>
  );
}
render内をアロー関数で書かないと、render時にuseStateが呼ばれてしまい、再びrenderされ、そこでもuseState⇒renderm⇒useState⇒render...というループに陥ります。
useEffectでの無限ループ
React ComponentライフサイクルとuseEffectが実行されるタイミングがバッティングしている時や、useEffectで発生した副作用を依存配列で参照している時に無限ループになる。
コンポーネントのstateが更新される度に、Reactはコンポーネントをレンダリングしますが、useEffectはコンポーネントがレンダリングされる度に、呼び出されるため無限ループになる。
※あまり使わない例
import React, { useState, useEffect } from "react";
export const Hoge= () =>{
  const [count, setCount] = useState(0);
  useEffect(() => setCount(count+1));
  return (
    <div>
      <div>Count: {count}</div>
    </div>
  );
}
これに関しては ESLint の eslint-plugin-react-hooks を設定しておけば Warning が表示されるので容易く気付けます。
React Hook useEffect contains a call to 'setCount'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [count] as a second argument to the useEffect Hook.eslintreact-hooks/exhaustive-deps