レンダリング中に異なるコンポーネントの状態更新を行う時は気を付ける
以下のようなコードがあるとする。
"use client";
import { useState } from "react";
function ParentComponent() {
const [parentState, setParentState] = useState("initial");
return (
<div>
<h1>Parent State: {parentState}</h1>
<ChildComponent setParentState={setParentState} />
</div>
);
}
function ChildComponent({ setParentState }: { setParentState: (value: string) => void }) {
// この関数内で親コンポーネントの状態を変更
setParentState("updated");
return <div>Child Component</div>;
}
export default ParentComponent;
これを実行すると、以下のようなエラーが出力される。
Cannot update a component (`ParentComponent`) while rendering a different component (`ChildComponent`). To locate the bad setState() call inside `ChildComponent`, follow the stack trace as described in https://react.dev/link/setstate-in-render
これは、ChildComponentのレンダリング中にParentComponentのsetParentStateを直接呼び出し、状態を更新しようと試みたことにより発生したエラーである。
Reactは、レンダリング中に他のコンポーネントの状態更新を禁止している。これを防ぐには、以下のように修正する。
"use client";
import { useEffect, useState } from "react";
function ParentComponent() {
const [parentState, setParentState] = useState("initial");
return (
<div>
<h1>Parent State: {parentState}</h1>
<ChildComponent setParentState={setParentState} />
</div>
);
}
function ChildComponent({ setParentState }: { setParentState: (value: string) => void }) {
useEffect(() => {
// レンダリング後に状態を更新
setParentState("updated");
}, [setParentState]);
return <div>Child Component</div>;
}
export default ParentComponent;
useEffectを使用する事で、ChildComponentのレンダリング後に状態更新されるよう、実行タイミングをコントロールが出来る。