🐕
普段あまり使わないフックを使いこなしたい (useReducer編)
はじめに
今回から普段あまり使用しないReactのフックを使いこなせるように記事にまとめていこうと思いました。
第一回目は活用の幅の広そうなuseReducer
です。
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
の引数であるstate
とaction
を用いてカウンターを実現しています.
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
よりシンプルに実装できたり、保守性の高いコードが書けたりすると思うので、使いこなせるようになりたいと思いました!
間違いやわかりづらい点、その他の使い方ありましたら、コメントいただけます幸いです。
参考
Discussion