🐕

普段あまり使わないフックを使いこなしたい (useReducer編)

2023/11/08に公開

はじめに

今回から普段あまり使用しないReactのフックを使いこなせるように記事にまとめていこうと思いました。
第一回目は活用の幅の広そうなuseReducerです。

useReducerとは

https://ja.react.dev/reference/react/useReducer
useReducerは第一引数にstateを更新する関数を渡すことで、stateを更新することができるフックです。
ローカルのstateを管理するという点ではuseStateと同じです。

実際に使ってみる

チェックボックス(トグルボタン)

以下のコードでは第一引数で現在のstateと反対のbooleanを返すように記述しています。
仮にuseStateならsetterを用いてstateを更新する記述が必要になってくるので、useReducerを用いた記述の方が少しだけシンプルに書けました。

export const UseReducer = () => {
  const checkboxId = useId()
  const [checked, toggle] = useReducer((s) => !s, false)

  return (
    <>
      <div>
        <input
          type="checkbox"
          id={checkboxId}
          name={checkboxId}
          checked={checked}
          onChange={toggle}
        />
      </div>
      {checked ? 'チェックされている' : 'チェックされていない'}
    </>
  )
}

カウンター

以下のコードではdispatchの引数であるstateactionを用いてカウンターを実現しています.
decrementの際は別でdecrementBy関数を作りその中でincrementByを呼び出しています。

export const UseReducer = () => {
  const [value, incrementBy] = useReducer(
    (v: number, inc: number) => v + inc,
    0,decrementBy
  )

  const decrementBy = (value: number) => incrementBy(-value)

  return (
    <>
      <button onClick={() => decrementBy(1)}>- 1</button>
      {value}
      <button onClick={() => incrementBy(1)}>+ 1</button>
    </>
  )
}

オブジェクトのstate管理

以下のコードではuseReducerの第一引数内で現在のstateと新しいstateをスプレッド構文で展開することでオブジェクトのstateの更新を実現しています。

type UserState = {
  firstName: string
  lastName: string
  email: string
}

type UserUpdate = Partial<UserState>

export const UseReducer = () => {
  const [user, updateUser] = useReducer(
    (currentState: UserState, update: UserUpdate) => ({
      ...currentState,
      ...update,
    }),
    {
      firstName: '',
      lastName: '',
      email: '',
    },
  )

  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target
    updateUser({ [name]: value })
  }

  return (
    <>
      <div>
        <input
          type="text"
          name="firstName"
          value={user.firstName}
          onChange={onChange}
        />
        <input
          type="text"
          name="lastName"
          value={user.lastName}
          onChange={onChange}
        />
        <input
          type="email"
          name="email"
          value={user.email}
          onChange={onChange}
        />
      </div>
    </>
  )
}

おわりに

今回はuseReducerを使いこなすために色々な使い方を試してみました。
場合によってはuseStateよりシンプルに実装できたり、保守性の高いコードが書けたりすると思うので、使いこなせるようになりたいと思いました!
間違いやわかりづらい点、その他の使い方ありましたら、コメントいただけます幸いです。

参考

https://ja.react.dev/reference/react/useReducer
https://www.code-insights.dev/posts/creative-ways-of-using-usereducer

Discussion