できない.dev

React で「Cannot update a component while rendering a different component」が消えない

レンダリング中に別コンポーネントの set 関数を呼ぶと出る警告。
状態更新は render の外(イベントハンドラや useEffect)へ移す。

公開:

要約

Cannot update a component (A) while rendering a different component (B) は、コンポーネント B のレンダリング中に、別のコンポーネント A の状態更新関数を呼んでしまったときに出る警告。

React ではレンダーは純粋であるべきで、描画の途中で他コンポーネントの state を書き換えてはいけない。
更新はイベントハンドラか useEffect へ移すのが基本。

よくある原因

  1. 即時実行: onClick={handleClick()} と書くと、クリック時ではなくレンダー時に関数が実行され、その中の setter が走る。
  2. レンダー中の setter 呼び出し: 子の描画中に props で受け取った親の setter をそのまま呼んでいる。
  3. 外部ストアの直接更新: レンダー本体で store の更新関数を呼んでいる。

解決策

1. 即時実行を関数に変える

// NG: レンダー時に呼ばれてしまう
<button onClick={handleClick()}>送信</button>
 
// OK: クリック時に呼ばれる
<button onClick={() => handleClick()}>送信</button>

イベントに渡すのは「呼び出した結果」ではなく「関数そのもの」にする。

2. 副作用は useEffect に入れる

useEffect(() => {
  onReady(id);
}, [id, onReady]);

親へ通知するような更新は、レンダー後に一度だけ走る useEffect に移す。

3. 更新の責務を親側に置く

子のレンダー中に親 state を変えたくなったら、設計を見直す。
多くの場合、そのロジックは親のイベントハンドラや effect に置くのが正しい。

この記事は役立ちましたか?