React Custom Hooksのサンプル集

※ 本記事は `useState`, `useEffect`, `useContext` 等の Built-in Hooks については理解していることを前提としています。

React v16.8 でリリースされる予定(元はv16.7だったが延期)の Hooks 機能ですが、その醍醐味は Custom Hooks にあると思います。
しかし慣れない内は Custom Hooks を作るのは難しいと思いサンプルを集めました。眺めることで Custom Hooks の勘所のようなものが掴めればいいなと。

# TL;DR

サンプル集のセクションを参照

# Custom Hooksとは

Custom Hooksとは特定の Hooks API のことではなく、それらを組み合わせて作る独自のHooksです。


簡単な例をあげてみます。
メールアドレスとパスワードがある入力フォームの場合、 Built-in Hooks だけを使って書くと次のようになると思います。

```jsx
() => {
  const [email, setEmail] = useState("")
  const [password, setPassword] = useState("")

  return (
    <form>
      <input type="email" value={email} onChange={(e) => setEmail(e.target.value) } />
      <input type="password" value={password} onChange={(e) => setPassword(e.target.value) } />
    </form>
  )
}
```

React v16.7 以前と比較すると、スマートにかけるようになりましたが、冗長な部分がありますよね。
そこで Custom Hooks の出番です。

```jsx
const useInput = initialValue => {
  const [value, set] = useState(initialValue)

  return { value, onChange: (e) => set(e.target.value) }
}

() => {
  const emailProps = useInput("")
  const passwordProps = useInput("")

  return (
    <form>
      <input type="email" {...emailProps} />
      <input type="password" {...passwordProps} />
    </form>
  )
}
```

useInput という Custom Hook を作ることでより簡潔に書くことができました。（簡単な例であまりメリットを感じないかも知れませんが）

# サンプル集

## [React Hooks 大喜利 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/react-hooks-ogiri)

2018年の Advent Calendar で何とお一人で23個のパターンを見せてくれました。(他の2日は導入等の前置き的な記事)
モダンなUIやアニメーションを Custom Hooks でどう実装するのかという点が大変勉強になりました。（もちろんそれだけではありませんよ）
Qiitaの記事では考え方とか設計方法の説明に重点が置かれており、掲載コードは一部省略されています。本気で勉強したい場合は [Github のリポジトリ](https://github.com/takefumi-yoshii/react-hooks-ogiri) をcloneして実コードと並べて読むといいと思います。（私もカレンダー期間中はほぼ毎日、アプリを動かしながら実コードとQiita記事を読みながらフムフム言ってました）

余談ですけど、`useRef` を通常用途とは異なる使い方をされていて、「なるほどなぁ、そういう使い方もできるのか」と感銘を受けたんですけど、今検索しても見つけられず・・・記憶違いかなぁ。
通常は `const ref = useRef(); return <div ref={ref} />` のような使い方をされると思いますが、たしかその記事ではプリミティブな値(少なくとも HTMLElement ではない)を扱っていて、代入も自前でやってたはず。

## [useHooks - Easy to understand React Hook recipes](https://usehooks.com/)

`useHistory`, `useKeyPress` 等、どちらかと言えば機能的な Custom Hooks が16パターン紹介されています。

## [Building a GraphQL HOC with React Hooks - wawhal - a personal blog](https://wawhal.in/posts/graphql-hoc-with-react-hooks/)

GraphQL のクエリを扱うサンプル。(1パターンだけ)

## [Making setInterval Declarative with React Hooks — Overreacted](https://overreacted.io/making-setinterval-declarative-with-react-hooks/)

Custom Hooks で setInterval を扱うパターン。(おそらく当たり前過ぎて記事中では触れられていないけど setTimeout も同じ考え方)
要点としては、以下の感じ。

* コールバック関数は `useRef` で参照を保持しておく。（コールバック関数が変わるたびに参照も変える）
* `useEffect` で `setInterval (or setTimeout)` して、その戻り値( `intervalId (or timerId)` ) を `clearInterval (or clearTimeout)` する関数を返す。遅延時間が変わるたびに `setInterval (or setTimeout)` で登録しなおす。

~~要点と言いつつ、コードをそのまま日本語にした感じになってしまった~~

## [react-hooks-async](https://github.com/dai-shi/react-hooks-async)

react-hooks-async は npm ライブラリだけど、非同期処理の扱いの参考になる。
遅延処理(timeout, delay) や通信処理(fetch, axios)のほか、WebAssembly なんかも扱っている。
ちなみに1hook(1ファイル)あたり数十行〜百行未満なので、読みやすく理解もしやすい。

前出の「Making setInterval Declarative with React Hooks — Overreacted」の内容に加え、非同期処理の中断(abort)機能も実装されている。

## [React Portals with Hooks](https://www.jayfreestone.com/writing/react-portals-with-hooks/)

モーダル表示などでよく使われる Portal (ReactDOM.createPortal) との組み合わせ。

## [10 Custom React Hooks you Should Have in Your Toolbox](https://blog.bitsrc.io/10-react-custom-hooks-you-should-have-in-your-toolbox-aa27d3f5564d)

npm ライブラリ群の紹介記事だけど、使用例を見るとライブラリの中でどういったことをやっているかは何となく想像でき参考になる。

## [Collection of React Hooks](https://nikgraf.github.io/react-hooks/)

タイトル通り、Hooksのコレクション。名称での検索以外にも `tag:fetch` のようにタグ検索や、 `hook:useState` のようにBuilt-in Hooks での検索もできる。
たとえば「useRefは実際にはどのような使われ方しているんだろう」というような視点で参考になるかも。

## [beautiful-react-hooks](https://github.com/beautifulinteractions/beautiful-react-hooks)

以下のような汎用的なhooks集npm

* useGlobalEvent
* usePreviousValue
* useValueHistory
* useMediaQuery
* useOnlineState
* useViewportSpy
* useGeolocation
* useDrag
* useMouse
* useLifecycle
* useWindowResize
* useWindowScroll
* useTimeout
* useInterval
* useDebouncedFn

## [awesome-react-hooks](https://github.com/rehooks/awesome-react-hooks)

Hooks のチュートリアル・周辺ツールやライブラリのリンク集

---

最初は上記リンクで紹介されているパターン1つずつ概要を書こうと思ったんですが、 ~~途中で挫折~~ 下手な説明よりも実際にコードを見てもらうのが早いと思い、ルートページのリンクのみとしています。
他にも見つけたら追加していきます。もしおすすめのサンプル集などありましたら教えてください。