React Hooks

関数コンポーネントで色々できるようになるReact Hooksです。
Reactいじったことある人前提で書いていきます。

# 目次
[useState](#useStsate)
[useeffect](#useeffect)
[uselayouteffect](#uselayouteffect)
[usecontext](#usecontext)
[usereducer](#usereducer)
[usecallback](#usecallback)
[usememo](#usememo)
[useref](#useref)
[useimperativehandle](#useimperativehandle)

## useState
コンポーネント内での状態管理を実装できます。

コードで再現すると
```jsx
const { useState } = require("react")

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

  return(
    <div>
      <p>set count: {count}</p>

      <div>
        <button onClick={() => setCount(count - 1)}>-</button><button onClick={() => setCount(count + 1)}>+</button>
      </div>
    </div>
  )
}

export default UseStateSample
```

これの結果が
![qiita1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/4ce2ae9e-1755-c0b8-6f63-27ae508646b3.gif)

実際にボタンが押されると、ボタンに応じてカウントが変更されて数字も変わっています。
`useState`の使い方は

```js
const [state, setState] = useState(initialState)
```

のように2つの要素を渡します。1つ目の要素には初めは初期値として`initialState`で設定したものが入ります。2つ目の要素は1つ目の要素を更新するために使います。`useState`の`initialState`には`state`の初期値を設定しています。

今回の例だと`count`という状態変数を設定し、`setCount`を使って`count`を変更して、`useState`に`count`の初期値を0で設定しています。

`state`、`setState`は任意の名前で決められます。`setState`の方は特になければ寛容的に`set + stateでつけた名前の先頭一文字目を大文字`で付けています。Reactを触ってる人はなんとなくわかると思います。

React18以降と以前では若干動きが異なると思います。自動バッチングやflushSyncとか

自動バッチングやflushSyncのわかりやすかった記事：

https://ja.reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#automatic-batching

https://github.com/reactwg/react-18/discussions/21

https://www.asobou.co.jp/blog/web/react18beta-autobatch

https://note.com/umotion/n/nadda0d47801c

https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973

## useEffect
副作用を実装できます。

ここでいう副作用は、*関数の外に影響を与えるもの*と*関数の引数以外で戻り値に影響を与えるもの*となっています。例えば、DOMの書き換え、データ読み込み、タイマー、ロギングなどがあり、これらは`useEffect`を使用して扱うことができます。

クラスコンポーネントを使う人からすると`useEffect`は`componentDidMount`、`componentDidUpdate`、`componentWillUnmount`をまとめたものとなっています。

データ読み込みの例を使って説明すると：
```jsx
import { useEffect, useState } from "react"

function UseEffectSample() {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch('https://www.reddit.com/r/reactjs.json')
    .then(response => response.json())
    .then(json => setData(json.data.children.map(content => content.data)))
  })

  return(
    <div>
      {data.map(d => (
        <li key={d.id}>{d.title}</li>
      ))}
    </div>
  )
}

export default UseEffectSample
```

これを実行すると
![スクリーンショット 2023-01-14 15.01.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/1744fb90-2cbf-fe8d-a555-47a197fc7322.png)

と表示されてしっかり外部からデータを取得することができます。

実はこのコードだと少し問題があります。これだとレンダーの完了時に毎回呼び出されてしまいます。それをさせないために`useEffect`には配列で受け取れる第２引数があります。
先ほどのコードを少し作り替えていきます。今回は二つのコンポーネントを使っていきます。

```jsx:React.js
import { useEffect, useState } from "react"

function Reddit({subreddit}) {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch(`https://www.reddit.com/r/${subreddit}.json`)
    .then(response => response.json())
    .then(json => setData(json.data.children.map(content => content.data)))
  }, [subreddit])

  return(
    <div>
      {data.map(d => (<li key={d.id}>{d.title}</li>))}
    </div>
  )
}

export default Reddit
```

```jsx:UseEffectSample2.js
import { useState } from "react"
import Reddit from "./Reddit"

function UseEffectSample2() {
  const [inputValue, setInputValue] = useState('')
  const [submitValue, setSubmitValue] = useState('reactjs')

  const handleSubreddit = (event) => {
    setInputValue(event.target.value)
  }

  const handleSubmit = (event) => {
    event.preventDefault()
    setSubmitValue(inputValue)
  }

  return(
    <div>
      <form onSubmit={handleSubmit}>
        <label>
          input subreddit:
          <input type='text' name='subreddit' onChange={handleSubreddit}></input>
        </label>

        <input type='submit' value='submit'></input>
      </form>

      <Reddit subreddit={submitValue}></Reddit>
    </div>
  )
}

export default UseEffectSample2
```

これを実行すると

![qiita2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/293121a2-a55b-90eb-413b-c8c82fe35679.gif)

ここで何をしているかの説明は、フォームで入力したテキストをRedditのsubredditのAPIに使って、jsonがあれば画面を変更して表示するようにしています。

ここで重要なのが`useEffect`の第２引数に`subreddit`が入っています。これは`subreddit`が変更されると次のレンダー時に`subreddit`が変更されていれば`useEffect`が走ります。

`useEffect`の第２引数では配列で設定することができ、`useEffect`を実行するタイミングを調整することができます。初回レンダーのみで呼び出したい時は第２引数を`[]`にし、値の変更に応じて`useEffect`を実行したいときは監視したい値を第２引数に配列で設定することでできます。

クラスコンポーネントでは`componentWillUnmount`でクリーンアップを行っていたことを`useEffect`でも行うことができます。クリーンアップを先ほどの`Reddit.js`の例で少し書き加えると
```jsx:Reddit.js
import { useEffect, useState } from "react"

function Reddit({subreddit}) {
  const [data, setData] = useState([])
  const controller = new AbortController()
  const signal = controller.signal

  useEffect(() => {
    fetch(`https://www.reddit.com/r/${subreddit}.json`, { signal })
    .then(response => response.json())
    .then(json => setData(json.data.children.map(content => content.data)))

    // クリーンアップ
    return () => {
      controller.abort()
    }
  }, [subreddit, data])

  return(
    <div>
      {data.map(d => (<li key={d.id}>{d.title}</li>))}
    </div>
  )
}

export default Reddit
```

のようにクリーンアップは`useEffect`の`return`を追加してその中にクリーンアップ処理を追加できます。

ところで最初の方で`useEffect`は`componentDidMount`、`componentDidUpdate`、`componentWillUnmount`をまとめたものと言いましたが、どの辺がまとまったものなのかというと：
- `componentDidMount`は`useEffect`の第２引数を設定した状態
- `componentDidUpdate`は`useEffect`自体が`state`を監視して、`state`に更新があれば実行されるところ
- `componentWillUnmount`は`useEffect`のクリーンアップの部分

になっていると思います。

`useEffect`で参考になったリンクたち：

https://ja.reactjs.org/docs/hooks-reference.html#useeffect

https://ja.reactjs.org/docs/hooks-effect.html

https://nomurabbit.hatenablog.jp/entry/20211213/1639325651

↓`useEffect`の第２引数を省略しちゃいけない理由

https://ja.reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

↓何で参考にしたのか忘れました

https://ja.reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often

↓`useEffect`が`componentDidUpdate`の機能を備えた理由

https://ja.reactjs.org/docs/hooks-effect.html#explanation-why-effects-run-on-each-update

↓`useEffect`の第２引数を設定することによるパフォーマンス向上

https://ja.reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

### useLayoutEffect
`useEffect`のおまけとして書いていきます。
これの機能は`useEffect`とほとんど同じです。使い方は`useEffect`と変わらず、第１引数と第２引数があり、`useEffect`の使い方と意味は同じです。
唯一の違いは*呼び出されるタイミングが画面が描画される前か後か*です。`useLayoutEffect`は描画される前に呼び出されます。実際のところこれを使う場面は稀だと思います。下手に使おうとするとパフォーマンスに影響が出たりするので、初めに絶対に表示させたいものだけを実装することをお勧めします。

`useLayoutEffect`の参考サイト

↓`useLayoutEffect`のドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#uselayouteffect

https://zenn.dev/syu/articles/6b96e34535b33e

## useContext
クラスコンポーネントにもあったコンテキストのフック版です。
クラスコンポーネントと比べるとちょっと実装が楽になった感じです。コンポーネントを3つ使って説明します。

```jsx:UseContextSample.js
import { createContext } from "react"
import ComponentA from "./ComponentA"

export const ContextToPassToComponentB = createContext()

function UseContextSample() {
  return(
    <div>
      <ContextToPassToComponentB.Provider value='ComponentBに渡したよ'>
        <p>ここが1番上のコンポーネント</p>
        <ComponentA anyProps='親から受け取った'></ComponentA>
      </ContextToPassToComponentB.Provider>
    </div>
  )
}

export default UseContextSample
```

このコンポーネントが1番上のコンポーネントとして使います。
次が`UseContextSample.js`の子となる`ComponentA.js`です。

```jsx:ComponentA.js
import ComponentB from "./ComponentB"

function ComponentA({anyProps}) {
  return(
    <div>
      <p>ComponentA</p>
      <p>{anyProps}</p>

      <ComponentB></ComponentB>
    </div>
  )
}

export default ComponentA
```

次が`ComponentA.js`の子となる`ComponentB.js`です。

```jsx:ComponentB.js
import { useContext } from "react"
import { ContextToPassToComponentB } from "./UseContextSample"

function ComponentB() {
  const context = useContext(ContextToPassToComponentB)

  return(
    <div>
      <p>ComponentB</p>
      <p>{context}</p>
      <p></p>
    </div>
  )
}

export default ComponentB
```

コンテキストの説明は不要だと思いますが、コンテキストを使わないと`UseContextSample.js`から`ComponentB.js`へと値を渡すには`props`を一旦`ComponentA.js`を通してから渡すか`UseContextSample.js`に直接`ComponentB`コンポーネントを実装するかになると思います。階層が少なければなんとかなると思いますが、１０0階層以上とか1つのコンポーネントに100個以上(どこかのプロジェクトであるかもしれぬ...)になった場合は`props`の追跡が大変になると思います。なるべくそうならないためにコンテキストが有効になると思います。

実際にこのコードを実行すると

![スクリーンショット 2023-01-19 1.54.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/f419175e-898c-fb2c-ee7a-1cecddd4d4e9.png)

となって`UseContextSample.js`から`ComponentB.js`に直接値を渡せています。今回は普通の値を渡していますが`state`も渡せたりできます。

↓`useContext`の公式ドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#usecontext

https://qiita.com/seira/items/fccdf4e73c59c491558d

## useReducer
`useReducer`は`useState`の拡張版みたいなものです。

定義は

```js
const [state, dispatch] = useReducer(reducer, initialArg, init);
```

となっています。これは公式的にはReduxをやってると馴染みがあるらしいのですが私はやってないのでよくわからないです。私自身使ったことないので触った感じで書いていきます。

普段使っている分には`state`の管理は`setState`で十分ですが、複数の値にまたがる複雑な`state`ロジックがある場合や、前の`state`に基づいて次の`state`を決める必要がある場合（公式から）や`useContext`で少し触れたように`state`の受け渡しが関わる複数階層コンポーネントへの受け渡しの時に有効です(パフォーマンスの最適化)。

`useReducer`のよくある例だと第３引数まで使われているものが少ないので、まずは第１と第2が使われているものを使っていきます。次のコードは2で足したり割ったりする四則演算を例に書いていきます。

```jsx:UseReducerSample.js
import { useReducer } from "react"

function UseReducerSample() {
  const initResult = 0.0

  const [result, calculation] = useReducer((currentSResult, action) => {
    let type = action.type

    switch(type) {
      case 'plus':
        return currentSResult + 2
      case 'minus':
        return currentSResult - 2
      case 'multiply':
        return currentSResult * 2
      case 'divide':
        return currentSResult / 2
      case 'reset':
        return initResult
    }
  }, initResult)

  return(
    <div>
      <p>この値から計算します：{result}</p>
      <p><button onClick={() => calculation({type: 'plus'})}>2足す</button></p>
      <p><button onClick={() => calculation({type: 'minus'})}>2減らす</button></p>
      <p><button onClick={() => calculation({type: 'multiply'})}>2でかける</button></p>
      <p><button onClick={() => calculation({type: 'divide'})}>2でわる</button></p>
      <p><button onClick={() => calculation({type: 'reset'})}>リセット</button></p>
    </div>
  )
}

export default UseReducerSample
```

これを実行すると

![qiita3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/18b05db1-c830-f2ea-9bf9-12d094a5df25.gif)

のように２で四則演算を実装できました。

このコードでの`useReducer`の説明をすると、`[result, calculation]`の部分は`result`は`useState`の部分で言う`state`になり、`culculation`は`result`の結果を出す関数になってます。そして`useReducer`の第１引数は`culculation`が呼び出されたときに実際に実行する処理を実装する部分になります。この中で関数に渡された値から計算して`result`に出していくことをしています。第２引数は`result`の初期値の設定部分です。

もう少し説明していくと、第１引数で実装した関数内で`(currentSResult, action)`がありますが、`currentSResult`は名前の通り現在の`result`、すなわち今の`state`を表しています。`action`は`culculation`で受け取った引数が入ります。

ついでにこれを`setState`を使ったバージョンで書くと

```jsx:UseStateSample2.js
import { useState } from "react"

function UseStateSample2() {
  const initResult = 0.0

  const [result, setResult] = useState(initResult)

  const calculation = (action) => {
    let type = action.type

    switch(type) {
      case 'plus':
        setResult(result + 2)
        break
      case 'minus':
        setResult(result - 2)
        break
      case 'multiply':
        setResult(result * 2)
        break
      case 'divide':
        setResult(result / 2)
        break
      case 'reset':
        setResult(initResult)
        break
    }
  }

  return(
    <div>
      <p>この値から計算します：{result}</p>
      <p><button onClick={() => calculation({type: 'plus'})}>2足す</button></p>
      <p><button onClick={() => calculation({type: 'minus'})}>2減らす</button></p>
      <p><button onClick={() => calculation({type: 'multiply'})}>2でかける</button></p>
      <p><button onClick={() => calculation({type: 'divide'})}>2でわる</button></p>
      <p><button onClick={() => calculation({type: 'reset'})}>リセット</button></p>
    </div>
  )
}

export default UseStateSample2
```

で表現できます。

最初のところで`useReducer`には第3引数があることを書きました。これの正体は`state`の初期化を関数で実装できるものになってます。さっきのコードを少し書き換えると

```jsx:UseReducerSample.js
import { useReducer } from "react"

function UseReducerSample() {
  const initResult = 0.0

  // これ追加（初期値に100を追加）
  const init = (initValue) => {
    return initValue + 100
  }

  const [result, calculation] = useReducer((currentSResult, action) => {
    let type = action.type

    switch(type) {
      case 'plus':
        return currentSResult + 2.0
      case 'minus':
        return currentSResult - 2.0
      case 'multiply':
        return currentSResult * 2.0
      case 'divide':
        return currentSResult / 2.0
      case 'reset':
        return initResult
    }
  }, initResult, init)  // 第3引数にinit追加

  return(
    <div>
      <p>この値から計算します：{result}</p>
      <p><button onClick={() => calculation({type: 'plus'})}>2足す</button></p>
      <p><button onClick={() => calculation({type: 'minus'})}>2減らす</button></p>
      <p><button onClick={() => calculation({type: 'multiply'})}>2でかける</button></p>
      <p><button onClick={() => calculation({type: 'divide'})}>2でわる</button></p>
      <p><button onClick={() => calculation({type: 'reset'})}>リセット</button></p>
    </div>
  )
}

export default UseReducerSample
```

これを実行すると

![スクリーンショット 2023-01-20 2.28.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/df87b2e4-d02e-87e6-b299-20cbff138c33.png)

ほとんど変わらないのですが、初期値が０なのが嫌だったのか元々ある初期値に100を追加するように設定しています。`init`で受け取った引数から100を追加することで初期値に100が追加された状態の初期値が初めに表示されています。`useReducer`ではこの関数を第3引数に入れて、第2引数を`init`の引数として受け取っています。
これを使うことでReduxのようなことができるのですが公式的にはおすすめされていません。

参考にしたサイト：

↓`useReducer`の公式ドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#usereducer

↓`useReducer`を使う利点1

https://ja.reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down

https://devsakaso.com/react-usereducer/

## useCallback
メモ化されたコールバックを実装できます。

メモ化自体はパフォーマンスの最適化として使われますが、Reactでは少し意味が異なり、`useCallback`ではコンポーネント間にある依存関係から不要なレンダーを防ぐときに有効になってきます（もちろん不要なレンダーが減るのでパフォーマンスが良くなるという意味にもなります）。

比較のため、`useCallback`を使わなかった例と使う例を書いていきます。

`useCallback`を使わなかった例は

```jsx:ComponentSample.js
import { useState } from "react"
import ComponentC from "./ComponentC"

function ComponentSample() {
  console.log('親コンポーネントレンダー')

  const [count, setCount] = useState(0)
  const [count2, setCount2] = useState(0)

  // 子コンポーネントでボタンがクリックされた時に実行
  const handleClick = () => {
    setCount2(() => count2 + 1)
  }

  // 親コンポーネントでボタンをクリックすると実行
  const plusCount = () => {
    setCount(() => count + 1)
  }

  return(
    <div>
      <p>私が親です：{count}</p>
      <p>私は子です：{count2}</p>
      <button onClick={plusCount}>カウントを増やす</button>
      <ComponentC handleClick={handleClick}></ComponentC>
    </div>
  )
}

export default ComponentSample
```

```jsx:ComponentD.js
function ComponentD(props) {
  console.log('子コンポーネントレンダー')

  return(
    <div>
      <p><button onClick={props.handleClick}>ComponentDでカウントを増やす</button></p>
    </div>
  )
}

export default ComponentD
```

これを実行すると

![qiita4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/df6cf373-1831-9df0-aea5-4eaa4bc9cd71.gif)

のように親と子に実装されているボタンをクリックするたびに親子のコンポーネント両方ともレンダーされています。

この時、親コンポーネントでのみの処理をしている時にもかかわらず、子コンポーネントが呼び出されています。これが不要なレンダーと考えられます。これをなくすために`useCallback`があります。

`useCallback`を使った例は

```jsx:UseCallbackSample.js
import { useCallback, useEffect, useState } from "react"
import ComponentC from "./ComponentC"

function UseCallbackSample() {
  console.log('親コンポーネントレンダー')

  const [count, setCount] = useState(0)
  const [count2, setCount2] = useState(0)

  // 子コンポーネントでボタンがクリックされた時に実行
  const handleClick = useCallback(() => {
    setCount2(() => count2 + 1)
  }, [count2])

  // 親コンポーネントでボタンをクリックすると実行
  const plusCount = () => {
    setCount(() => count + 1)
  }

  return(
    <div>
      <p>私が親です：{count}</p>
      <p>私は子です：{count2}</p>
      <button onClick={plusCount}>カウントを増やす</button>
      <ComponentC handleClick={handleClick}></ComponentC>
    </div>
  )
}

export default UseCallbackSample
```

```jsx:ComponentC.js
import { memo } from "react"

function ComponentC(props) {
  console.log('子コンポーネントレンダー')

  return(
    <div>
      <p><button onClick={props.handleClick}>ComponentCでカウントを増やす</button></p>
    </div>
  )
}

export default memo(ComponentC)
```

これを実行すると、

![qiita5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/043dc32b-df45-b4be-354d-adcb864c5993.gif)

のように子コンポーネントが呼ばれず不要なレンダーが避けられるようになっています。

`useCallback`を使うときの注意点として、`useCallback`を使う先のコンポーネントに`memo`の中にコンポーネントを入れないと機能しないことに注意してください。`useCallback`の第2引数に`useEffect`のような配列がありますが、これは依存配列になっていて、`useeffect`と同じで、配列内の値が変更されると実行されます。

ただ、`useCallback`自体、普通のちょっとした関数と比べると多少パフォーマンスが高いので不要な仕様は控えるようにしたほうがいいです。本当に必要な時のみ使用するようにしてください。

参考にしたサイト：

↓`useCallback`の公式ドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#usecallback

https://stackoverflow.com/questions/56910036/when-to-use-usecallback-usememo-and-useeffect

https://weseek.co.jp/tech/3917/

https://zenn.dev/web_tips/articles/656af21ea850d5

## useMemo
メモ化された値を実装できます。

`useCallback`と使う場面がほとんど同じなので特に記載はないです。

参考にしたサイト：
`useMemo`公式ドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#usememo

## useRef
ミュータブルな`ref`オブジェクトを実装できます。これはミュータブルな値を`.current`に保存します。実際に値を使用するときは`ref(変数名はなんでも良い).current`で使用します。

Reactをよく使っている人はDOMにアクセスできるやつでいつもお世話になっているものですね。

使う用途としては先ほどの*DOMへのアクセスに使われること*と*ミュータブルなものとして値を保存するもの*として使えます。

まずミュータブルな値を保存するものとして使う例は

```jsx:UseRefSample.js
import { useRef, useState } from "react"

function UseRefSample() {
  let normalValue = '普通の値です'
  const [state, setState] = useState('stateの値です')
  const refValue = useRef('refの値です')

  // 値を変更しているがレンダーされたらなくなる
  const normalValueChange = (event) => {
    normalValue = event.target.value
  }

  const stateChange = (event) => {
    setState(event.target.value)
  }

  const refValueChange = (event) => {
    refValue.current = event.target.value
  }

  return(
    <div>
      <p>{normalValue}</p>
      <p>{state}</p>
      <p>{refValue.current}</p>

      <div>
        <p>普通の値：<input type='text' onChange={normalValueChange}></input></p>
      </div>

      <div>
        <p>stateの値：<input type='text' onChange={stateChange}></input></p>
      </div>

      <div>
        <p>refの値：<input type='text' onChange={refValueChange}></input></p>
      </div>
    </div>
  )
}

export default UseRefSample
```

これを実行すると

![qiita6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/a2ec5d43-a89a-2c9a-1c81-d26018afd652.gif)

というようになり、`ref`の値を変更してから`state`の値を変更すると`ref`の方の値も更新されています。ここで気づいた人もいるかもしれませんが、メモ化をしています。`useRef`は`state`のように値を変更しても再レンダリングされません。`state`が更新されて再レンダリングされても`ref`の値は保持されます。

そして、DOMにアクセスする例（こっちの方がいつも使われていると思います）は

```jsx:UseRefSample2.js
import { useRef } from "react"

function UseRefSample2() {
  const focusRef = useRef(null)

  const handleClick = () => {
    focusRef.current.focus()
  }

  return(
    <div>
      <p>フォーカスする対象：<input type='text' ref={focusRef}></input></p>
      <button onClick={handleClick}>フォーカス！！</button>
    </div>
  )
}

export default UseRefSample2
```

これを実行すると

![qiita7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/67269406-e0b0-bb84-5c05-dc884be81fc6.gif)

のようになります。`.current`にDOMの情報が保持されそこからDOMの操作を行うことができます。

参考にしたサイト：
↓`useRef`のドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#useref

インスタンス変数について

https://ja.reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables

オブジェクト作成の遅延方法

https://ja.reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily

https://devsakaso.com/react-useref/

## useImperativeHandle
子コンポーネントのメソッドを`ref`経由で親コンポーネントで使うことができます。
公式ドキュメントでもあるようにあまりこのフックを使うこと自体はおすすめされていません。おそらく使う場面はないとは思いますが一応書いていきます。

`useImperativeHandle`の使い方は

```
useImperativeHandle(ref, createHandle, [deps])
```

となっていて、第１引数には`ref`を入れて、第2引数にはそれぞれメソッドを定義していく場所で、第3引数は`useEffect`のように依存配列を入れるところです。ここでは第2引数までの例で説明していきます。

```jsx:UseImperativeHandleSample.js
import { useRef } from "react"
import ComponentF from "./ComponentF"

function UseImperativeHandleSample() {
  const parentRef = useRef(null)

  const handlefocus = () => {
    parentRef.current.focus()
  }

  return(
    <div>
      <ComponentF ref={parentRef}></ComponentF>
      <button onClick={handlefocus}>フォーカス！！</button>
    </div>
  )
}

export default UseImperativeHandleSample
```

```jsx:ComponentF.js
import { forwardRef, useImperativeHandle, useRef } from "react";

function ComponentF({props}, ref)  {
  const inputRef = useRef(null)

  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus()
  }))

  return(
    <div>
      <input ref={inputRef}></input>
    </div>
  )
}

export default forwardRef(ComponentF)
```

これを実行すると、

![qiita8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144079/60f9c44c-457a-788b-39ad-666c1f3a8e0e.gif)

となります。reactの`ref`の例がフォーカスばかりなのでフォーカス以外もやりたかったのですがなんも思いつかなかったので結局フォーカスにしました。

参考にしたサイト：
↓`useImperativeHandle`の公式ドキュメント

https://ja.reactjs.org/docs/hooks-reference.html#useimperativehandle

https://numb86-tech.hatenablog.com/entry/2019/12/06/122217

`forwardRef`で参考にしたサイト

https://devsakaso.com/react-forwardref/

https://ja.reactjs.org/docs/forwarding-refs.html

↓`forwardRef`公式ドキュメント

https://ja.reactjs.org/docs/react-api.html#reactforwardref

## 終わり
これくらいで終わろうと思います。他にも`useDeferredValue`、`useTransition`、`useId`もありますが機会があれば書いていきたいなと思います。