[[📚6章 ステート管理]]の続き
### 第7章 useEffect
`useEffect`は、コンポーネントの描画が完了した後に呼び出される。
副作用として実行したい処理を記述する。(値が変わった時に実行される処理など)
#### 7.1.1 依存配列
```jsx
// valの値が更新された時に、effectの中の処理が実行される
useEffect(() => {
console.log('typing')
}, [val])
// valもしくはphraseの値が変わった時に実行する
useEffect(() => {
console.log('typing')
}, [val, phrase])
// 空の配列を渡した時は、初回描画時の時だけ実行される
useEffect(() => {
console.log('typing')
}, [])
```
戻り値として、別の関数を返した場合、 コンポーネントがツリーからアンマウントされた時に実行される
```jsx
useEffect(() => {
console.log('typing');
return () => goodbyeChime.play();
}, [])
```
#### 7.1.2 依存配列の同一性チェック
```js
const a = [1,2,3]
const b = [1,2,3]
a === b; // false
// 同じインスタンスを比較すると同一と評価される
const a = b = [1,2,3]
a === b; // true
```
解決策としてuseMemoを使って、変数の値をキャッシュする
```jsx
function WordCount({ children = "" }) {
// childrenを空白スペースごとに配列にしてメモ化する
const words = useMemo(() => children.split(" "), [children])
useEffect(() => {
console.log("fresh render");
// memo化したwordsを使うことで同じ値をもった配列を同一インスタンスとして判定できる
}, [words])
// return
}
```
関数のメモ化は`useCallback`を使う
```jsx
const fn = useCallback() => {
console.log("hello");
console.log("world");
}
useEffect(() => {
console.log("fresh render");
fn()
// メモ化したfnをここで呼んでいる
}, [fn])
```
`useEffect`に似ている関数として、`useLayoutEffect`がある
`useEffect`は、コンポーネントの描画関数が呼び出されて、画面に反映した後に呼ばれるが、`useLayoutEffect`は、画面に反映する前に呼び出される。
→ widthやheightなど画面のレイアウトをいじる時に、使うと良い
#### 7.2.1 フックの使い方に関するルール
- フックはコンポーネントのスコープで実行すること
- 一つのフックで多くのことをせず複数のフックに分離すること
- フックは常に描画関数のトップレベルから呼び出さなければならない
#### 7.3 useReducer
Array.reduceと似ている使い方
```js
const numbers = [1,2,3]
numbers.reduce((number, nextNumber) => number + nextNumber, 0) // 6
```
[【javascript】reduce - Qiita](https://qiita.com/chihiro/items/1047e40514a778c08baa)
```jsx
function Numbers() {
const [number, setNumber] = useReducer(
(number, newNumber) => number + newNumber,
0
)
// 要素がクリックされるたびにステート値に1が加算される
return <h1 onClick={() => setNumber(1)}>{number}</h1>
}
```