💁‍♂️

【React】useState()の初期値にpropsを使う時の注意点

2022/02/05に公開

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