Alex Banks/Eve Porcello オライリー・ジャパン 2021年08月06日頃
フック
7.3 useReducer
- 以下の
checked => !checked
のように、現在のステート値を受け取って新しいステート値を返す関数をリデューサーと呼ぶ。
const [checked, setChecked] = useState(false)
return (
<p><input type="checkbox" value={checked} onChange={()=>setChecked(checked => !checked)}>{checked ? "ON" : "OFF"}</p>
);
- useReducerフックを使うと、ステート更新のロジックを抽象化することができる。
- useReducerは第1引数にリデューサー、第2引数に初期値を取る。
- 戻り値の配列は、先頭要素がステート値、2番目の要素がリデューサーを実行(dispatch)するための関数
const [checked, toggle] = useReducer(checked =>!checked, false)
return (
<p><input type="checkbox" value={checked} onChange={toggle}/>{checked ? "ON" : "OFF"}</p>
);
- リデューサーは現在のステート値と任意の値の2つを引数に取ることもできる。
const [checked2, toggle2] = useReducer((checked2, num) => {
console.log(num)
return !checked2
},
return (
<p><input type="checkbox" value={checked2} onChange={()=> toggle2(777)}/>{checked2 ? "ON2" : "OFF2"}</p>
);
7.3.1 useReducerを使った複雑なステート管理
- useReducerはオブジェクトをステートとして扱う場合に効力を発揮する。
- 以下の例では、useStateを使った場合だと誤って
setUser({name: 'hogehoge'})
とするとオブジェクトが上書きされてしまう。
setUser({...user, name: 'hogehoge'})
とすれば問題ないのだが、useReducerを使った方がバグを産む可能性を下げることができる。
- 個人開発ではuseStateだけでも問題なく、複数人で開発する場合はuseReducerを使うべき、という意見もある。
function Reducer2() {
const initUser = {
id: 1,
name: 'hoge',
}
const [user, setUser] = useReducer((user, newValues) => ({...user, ...newValues}), initUser)
return (
<div>
{user.id}: {user.name}
<button onClick={()=>setUser({name: 'hogehoge'})}>setUser</button>
</div>
);
}
7.4 コンポーネントのパフォーマンス改善
- memo関数は関数コンポーネントをメモ化するためのトップレベル関数である。
- 以下のようにmemo関数を使うだけで、親コンポーネントが再描画されても、自身は再描画されなくなる。
import {memo} from 'react'
function Memo({msg}) {
console.log("rendering Memo")
return (
<div style={{border: "1px solid #ccc", padding: "50px"}}>
<h2>Mmeo.js</h2>
<p>{msg}</p>
</div>
);
}
export default memo(Memo);
7.4.1 いつパフォーマンスチューニングを行うか
- memo関数、useMemoフック、useCallbackフックは乱用される傾向がある。
- Reactはパフォーマンスが落ちないように設計されているので、まずはこれらを使わずに実装し、パフォーマンスに問題のあるコンポーネントのみこれらを使うべきである。
コメント