🔰

【React hooks】useStateの使い方あれこれ

2023/07/17に公開

この記事の内容

useStateとは

  • 関数コンポーネントでstateを管理(stateの保持や更新)するためのReactフック。
  • stateとは、コンポーネントが内部で保持する状態のことで、主に画面上に表示する項目、入力値などに使用しています。

ボタンを押して値を更新する

  • カウントアップボタンが押されるたびに、Count:{count}の値が増えていきます。
  const [count, setCount] = useState<number>(0);

  const handleClick = () => {
    setCount(count + 1)
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>カウントアップ</button>
    </div>
  )

【ポイント!】countの値が更新されるタイミングは再レンダリングの後

  • 状態の更新は非同期で行われます。
    そのため、setCountが呼び出された後、即座にcountの値が更新されるわけではないんです。
    Next.js(React)が状態の変更を検出し、コンポーネントが再レンダリングされたタイミングでcountの値が更新されます。
  • 流れはこう。
      1. ボタン押す
      1. handleClick関数が呼び出される
      1. setCountが呼び出されて、countの値が更新される
      1. コンポーネントが再レンダリングされ、最新のcountの値が表示される

親コンポーネントから子コンポーネントに関数を渡す

  • 子コンポーネントで状態を更新したい場合は、stateのset関数をpropとして子コンポーネントに渡すことができます。
  • さっきのstateを、親コンポーネントから子コンポーネントに渡してみましょう。
  • これで、子コンポーネントでの状態の更新を親コンポーネントに反映できます。
    親コンポーネント.tsx
const ParentComponent: React.FC = () => {
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <ChildComponent setCount={setCount} />
      <p>Count: {count}</p>
    </div>
  )
}

子コンポーネント.tsx

// 型の定義
interface ChildProps {
  // `React.SetStateAction<T>`は、useStateの型(ジェネリック型)
  // <>の中にstateの型を指定する
  setCount: React.Dispatch<React.SetStateAction<number>>;
}
                                              // ↓ 引数にsetCountを渡す
const ChildComponent: React.FC<ChildProps> = ({ setCount }) => {
  const handleIncrement = () => {
    // カウントアップ処理
    setCount((prevCount) => prevCount + 1)
  }

  return (
    <button onClick={handleIncrement}>子コンポーネントでカウントアップ</button>
  )
}

useStateの型にオブジェクト型を指定

  • useStateの型は、stringやnumberだけではなく、オブジェクト型も指定できます
  • オブジェクト型にして、入力フォームの情報をまとめて指定できます
// 入力フォーム情報
interface FormState {
  name: string
  age: number
  email: string
}

const MyComponent: React.FC = () => {
                                           // ↓ 入力フォームの型を指定
  const [formData, setFormData] = useState<FormState>({
    // 初期値を指定
    name: '',
    age: 0,
    email: '',
  });

オブジェクト型の値を更新する

  • ボタンを押したタイミングで値を更新してみる。
  • 例えばこんな感じで。・・・あれ?更新されない。。。
const clickChange = () => {
  formData.name = 'PONCHAN'
  setFormData(formData)
}
  • 参照先が変わっておらず、中身のデータが直接変わっている状態だとsetしても変わらないらしい。。

【ポイント!】更新する場合はスプレッド構文を使おう

  • setFormDataなどのset関数は、新しい状態に更新する場合、前の状態を変更せずに新しい状態を返す必要があります。
  • オブジェクトは参照型なので、前の状態を変更せずに新しいオブジェクトを作成する。
  • 直接変更すると同じ参照を持つ他の箇所にも影響を及ぼす可能性も。。。
スプレッド構文(...)を使用して新しいオブジェクトを作成しよう!
const clickChange = () => {
  const updatedFormData = {
    ...formData,
    name: 'YUMI'
  }
  setFormData(updatedFormData);
}
  • onChangeを使って、入力値が変わったものだけを更新もできる!
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 変更された入力値
    const { name, value } = e.target
    // 入力フォーム情報にセットする
    setFormData((prevFormData) => ({
      ...prevFormData,
      [name]: value,
    }))
  }

  return (
    <div>
      <input
        type="text"
        name="name"
        value={formData.name}
        onChange={handleChange}
      />

以上、普段使っているuseStateの使い方まとめでした!

Discussion