はじめに
- 個人開発しているアプリでガリガリコードを書いていたら、いつの間にかuseStateだらけになったので、スッキリさせた。
- ちなみに実際にリファクタしたcommit。
リファクタ前の状況
-
コードはこんなイメージ。実際はもっとstateが多く、コードの見通しが悪い状況でした。
あくまでイメージなので色々省略しまくっているのはご了承ください。useStateに焦点を当てるためです。
SignIn.jsx
const SignIn = () => {
const [ mail, setMail ] = useState('')
const [ pass, setPass ] = useState('')
const handleMail = (event) => {
setMail(event.target.value)
}
const handlePass = (event) => {
setPass(event.target.value)
}
return (
<div>
<p>メールアドレスとパスワードでログイン</p>
<div>
<p>メールアドレス</p>
<input
value={mail}
onChange={handleMail}
/>
</div>
<div>
<p>パスワード</p>
<input
value={pass}
onChange={handlePass}
/>
</div>
<button>ログインする</button>
<button>入力内容をクリア</button>
</div>
)
}
export default SignIn
複数のuseStateを一つのuseStateにまとめてしまう。
- ReduxのreducerやHooksのuseReducerの考え方に近いと思います。ちなみに感じたメリット・デメリットは以下のとおり。
- Vueで例えると複数のdataを一つのstoreにまとめてしまうイメージ。
- メリット
- 実装が簡単。
- 関連性のあるstateを一つのオブジェクトにまとめることで可読性アップ。
- 関連性の薄いプロパティをまとめてしまうと逆に可読性が落ちるので、その場合は分けたままの方が良い。
- デメリット
- イベントハンドラー(ここで言うhandleMail等)はプロパティ毎に必要なので、ここは一つにまとめられない。
-
【2022/4/5追記】
コメントでイベントハンドラーを一つにまとめるコードをご提案いただきました。まさにreducerっぽい実装ですね。
-
【2022/4/5追記】
- setter(ここで言うsetUser)の引数が冗長になる。
- イベントハンドラー(ここで言うhandleMail等)はプロパティ毎に必要なので、ここは一つにまとめられない。
SignIn.jsx
const SignIn = () => {
const [ user, setUser ] = useState({
mail: '',
pass: ''
})
const handleMail = (event) => {
setUser((user) => {
return {
...user,
mail: event.target.value
}
})
}
const handlePass = (event) => {
setUser((user) => {
return {
...user,
pass: event.target.value
}
})
}
return (
<div>
<p>メールアドレスとパスワードでログイン</p>
<div>
<p>メールアドレス</p>
<input
value={user.mail}
onChange={handleMail}
/>
</div>
<div>
<p>パスワード</p>
<input
value={user.pass}
onChange={handlePass}
/>
</div>
<button>ログインする</button>
<button>入力内容をクリア</button>
</div>
)
}
export default SignIn