できない.dev

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

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

公開: 更新:

実行例あり(2026-09-20 に実環境で検証)

要約

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

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

実行例

node:20 で試すと、レンダー中に親の状態を更新しても描画自体は最後まで通り、警告だけが出た。
更新を useEffect に移した版では同じ結果が警告なしで得られている。

$ node bad.js
Warning: Cannot update a component (`Parent`) while rendering a different component (`Child`). To locate the bad setState() call inside `Child`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
    at Child (/tmp/tmp.YAM0rUTKUB/bad.js:5:18)
    at div
    at Parent (/tmp/tmp.YAM0rUTKUB/bad.js:11:39)
レンダー自体は完了する(警告だけが出る)
$ echo $?
0
$ node solve_effect.js
警告なしで描画: {"type":"div","props":{},"children":[{"type":"span","props":{},"children":["child:7"]},{"type":"p","props":{},"children":["ready:7"]}]}
$ echo $?
0

— 2026-09-20 時点の出力

検証環境

検証日
実行環境
node:20 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  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 に置くのが正しい。

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