Reactのhooksをおさらいしておく

株式会社ココロファン - エンジニアリング事業部所属のhazamaです。
サイト制作・運用業務をメインに行っています。

ここ最近はずっとReactを触って過ごしています。
その中でhooksの理解がたまにぼやけてしまうので、備忘録も兼ねておさらいをしておこうと思います。
## useState
よく使われるhooksの1つ。
stateという言葉の通り、「状態」を表し管理している。
次のように配列の形で1つめはstateの変数、2つめはそのstateを更新する関数を入れる。
命名は自由につけられるが、2つめの関数は暗黙的に「set（1つめのstateの変数名）」とすることが一般的。
```react
const [state, setState] = useState(0);
```
以下はuseStateを使ったカウントアップ機能の実装例です。
ボタン押下時に再レンダリングされて、「＋」押下の度に数値が1つずつ増えていきます。
```react
import { useState } from 'react';

function App() {
  const [count, setCount] = useState(0); //初期値は「0」とするため、useState関数のカッコ内に0を設定

  const handleClick = () => {
    setCount(count + 1);
  }

  return (
    <div className="App">
      <button onClick={handleClick}>＋</button>
      <p>{count}</p>
    </div>
  )
}
```
再レンダリングされる仕組みとしては、Reactは仮想DOMの
「更新前」と「更新後」を比較し、差分があった箇所をリアルDOMに反映している。
差分箇所だけの再レンダリングとなるためパフォーマンスも良い。
仮想DOMについては以下の記事がわかりやすかったのでURLを記載しておきます。

https://qiita.com/seira/items/6767e222890c9890ecb9
## useEffect
こちらもよく使われるhooks。
DOMの変更やstate/propsの変更など（副作用）があった時、特定の処理を実行することができます。
以下はuseStateの紹介で使ったカウントアップ機能にuseEffectを追記したコードです。
```react
import { useEffect, useState } from 'react';
import './App.css'

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  }

  useEffect(() => {
    console.log('クリックされました');
  },[count]);

  return (
    <div className="App">
      <button onClick={handleClick}>＋</button>
      <p>{count}</p>
    </div>
  )
}
```
ここでは「+」を押下時にhandleClickが呼ばれ、「count」に1を足して再レンダリングしていますが、
「count」という変数が更新（再レンダリング）された時に、コンソールログを出すだけの処理になっています。
記述としては次のように、第二引数に依存する変数を記述し、
変更が検知されるとコールバック関数が呼ばれ処理が実行されます。

```react
useEffect(() => {
  console.log('クリックされました');
},[count]);
```

依存する変数が複数ある場合でも複数指定できます。
```react
useEffect(() => {
  console.log('クリックされました');
},[count, test, hoge]);
```
基本的にstate/propsの更新時に実行したいというケースが多いと思うので
useEffectを使う際は第二引数に依存変数ありきと考えても良いかと思います。
第二引数に空の状態（[]）で渡すとマウント/アンマウント時に一度だけ実行できるようですが、
依存する変数がないので更新時などでは処理は実行されません。

>もしも副作用とそのクリーンアップを 1 度だけ（マウント時とアンマウント時にのみ）実行したいという場合、空の配列 ([]) を第 2 引数として渡すことができます。こうすることで、あなたの副作用は props や state の値のいずれにも依存していないため再実行する必要が一切ない、ということを React に伝えることができます。これは特別なケースとして処理されているわけではなく、入力配列を普通に処理すればそうなるというだけの話です。

参考：フックAPIリファレンス
https://ja.reactjs.org/docs/hooks-reference.html#useeffect

## useRef
こちらは主にDOMへの参照として使われることが多く、特にinputタグに対して使われることが多い印象です。
以下はボタン押下時にinputタグの情報を参照するサンプルコードです。
```react
import { useRef } from 'react';
import './App.css'

function App() {
  const inputRef = useRef();
  
  const handleRef = () => {
    console.log(inputRef);
  }

  return (
    <div className="App">
      <h1>useRef</h1>
      <input type="text" ref={inputRef}/>
      <button onClick={handleRef}>UseRef</button>
    </div>
  )
}
```
ブラウザでコンソールを開くと以下のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1256886/d0c0c880-bdf0-b4ef-d992-64356127648c.png)
見慣れない情報まで取得していますが、例えば入力した文字列だけを取得したい場合、
上記のコンソールを見ると「current」の中の「value」に情報が入っているので、
次のようにすることで取得可能となります。
```react
const handleRef = () => {
  console.log(inputRef.current.value);
}
```
要素の高さや幅も取得でき、特定の位置までスクロールさせる際にも活用できます。

## その他のhookについて
- useContext
- useReducer
- useMemo
- useCallback
「useContext」や「useCallback」は使う機会も出てくる思いますが、「useReducer」と「useMemo」は
その機会があまりないと思われます。とはいえ覚えておくに越したことはないので、本記事とは別機会にて。

## 最後に
今回は普段よく使うであろうhooksのおさらいだけにしていますが、こうして文章に書きだすと
やっぱり理解が薄かったなと思う箇所がありました。
最近は学習したこと覚えておきたいことは、ノートにまとめるようにしています。
アナログなやり方ですが、個人的には書き出すことで何処が
理解できていないのだろうというのが実感できるので、
一度自分なりに文章にするのは大切だなと思いました。

これからも有意義な情報が発信できるよう、できるだけ記事をアップしていきたいと思います。