💁♂️
【React】useState()の初期値にpropsを使う時の注意点
Reactを使い始めて一年以上が経ちましたが、useState()の初期値にpropsを使った時に初歩的なところでハマりました。
問題のコード
App.tsx
import { useState } from "react";
function Child(props: { count: number }) {
const [count, setCount] = useState(props.count);
return <div>{count}</div>;
}
function App() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)} />
<div>{count}</div>
<Child count={count} />
</div>
);
}
export default App;
この👆コードでは、ボタンを押すとApp
コンポーネントのcountは変化しますが、Child
コンポーネントのcountは変化しません。0のままです。
なぜこうなるのかと言うと、React.useState()の初期値は一度しかセットされないからです。
なのでpropsがいくら変化しても、Child
コンポーネントのcountは0のままになります。
解決策
propsが変化した時にChild
コンポーネントのcountも一緒に更新したい場合は、React.useEffect()を使います。
App.tsx
- import { useState } from "react";
+ import { useState, useEffect } from "react";
function Child(props: { count: number }) {
const [count, setCount] = useState(props.count);
+ useEffect(() => {
+ setCount(props.count);
+ }, [props.count]);
return <div>{count}</div>;
}
function App() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)} />
<div>{count}</div>
<Child count={count} />
</div>
);
}
export default App;
このようにすれば、Child
コンポーネントのcountも更新されるようになります。
Discussion
propsをstate にコピーすることは、意図的に更新を無視する場合を除いて避けた方が良さそうです。
ご参考までに💁♂️