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 へ移すのが基本。
よくある原因
- 即時実行:
onClick={handleClick()}と書くと、クリック時ではなくレンダー時に関数が実行され、その中の setter が走る。 - レンダー中の setter 呼び出し: 子の描画中に props で受け取った親の setter をそのまま呼んでいる。
- 外部ストアの直接更新: レンダー本体で store の更新関数を呼んでいる。
解決策
1. 即時実行を関数に変える
// NG: レンダー時に呼ばれてしまう
<button onClick={handleClick()}>送信</button>
// OK: クリック時に呼ばれる
<button onClick={() => handleClick()}>送信</button>イベントに渡すのは「呼び出した結果」ではなく「関数そのもの」にする。
2. 副作用は useEffect に入れる
useEffect(() => {
onReady(id);
}, [id, onReady]);親へ通知するような更新は、レンダー後に一度だけ走る useEffect に移す。
3. 更新の責務を親側に置く
子のレンダー中に親 state を変えたくなったら、設計を見直す。
多くの場合、そのロジックは親のイベントハンドラや effect に置くのが正しい。