Reatの状態管理ライブラリRecoilを触ってみる(Hands-on)

## はじめに
Reactの状態管理ライブラリRecoilを触ってみました。最初は難しいのかなと思っていたのですが、触ってみるとただのグローバル変数とGetter/Setter使ってるだけじゃん！！ってなりました。知識を落とし込むためにも、Hands-on形式で記事にしております。(ちなみに、Hands-onでは下記成果物ができます。)

https://twitter.com/kkfactory0705/status/1540278047425056769

### Recoilとは
RecoilとはMeta社「旧facebook社」が提供する状態管理ライブラリ。現在は`0.7.4`版とメジャーリリースがまだですが、機能や安定した利用ができるようです。
![スクリーンショット 2022-06-24 19.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/8867b2a7-03dd-637a-4452-26c806df9959.png)

## Hands-on開始

```shell:ディレクトリ
~/develop/react/recoil/recoil_counter $ tree -I node_modules                                      
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx　　　　　　　　　　　　　　　　　　　　　　　　　　　←修正
│   ├── Counter.tsx  　　　　　　　　　　　　　 ←作成
│   ├── atom.ts　　　　　　　　　　　　　　　　　　　　　　　　　　　←作成
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
├── tsconfig.json
└── yarn.lock

2 directories, 21 files
```

```shell:プロジェクト作成
~/develop/react/recoil/recoil_counter $ yarn create react-app recoil_counter --template typescript
yarn add recoil
```

### ソースコードの中身

```tsx:App.tsx
import { FC} from 'react'
import { RecoilRoot } from 'recoil'
import Counter from './Counter'


const App: FC = () => {
  return (
    <div>
      <RecoilRoot>
          <div>
            <Counter />
          </div>
      </RecoilRoot>
    </div>
  )
}

export default App
```
→Recoilを利用する場合、`RecoilRoot`で囲う必要があります。

```ts:atom.ts
import { atom, selector } from "recoil"

// グローバル変数のcounterAtom
export const counterAtom = atom({
    key: 'counterAtom',
    default: 0,
  })

// グローバル変数のGetter/Setter 
export const counterSelector = selector<number>({
    key: 'counterSelector',
    get: ({ get }) => {
      const counter = get(counterAtom)
      return counter
    },
    set: ({ set }, newValue) => {
      set(counterAtom, newValue)
    },
  })
```
→Recoilのライブラリから`atom`と`selector`をimportしています。
`atom`はただのグローバル変数、`selector`はグローバル変数のGetter/Setterと考えるとわかりやすいでしょう。


```tsx:Counter.tsx
import { FC, memo } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import {counterAtom, counterSelector } from './atom'

const Counter: FC = memo(() => {
  const countValue = useRecoilValue(counterAtom) //グローバル変数を直接取得
  const [count, setCount] = useRecoilState(counterAtom) // グローバル変数を他の変数に代入し取得
  const [counter, setCounter] = useRecoilState(counterSelector) // グローバル変数のSelector経由で取得

  const handleClickCount = (count: number) => {
    setCount(count)
  }

  return (
    <>
      <h1>カウンターアプリ(Recoilで状態管理)</h1>
      <div className="div">
        <h2>カウント値</h2>
        <span>{countValue}</span>
      </div>
      <div className="div">
        <div>
          <h2>グローバル変数を直接変更！！！</h2>
        </div>
        <div>
          <button onClick={() => handleClickCount(count - 1)}>-</button>
          <span>{count}</span>
          <button onClick={() => handleClickCount(count + 1)}>+</button>
        </div>
      </div>
      <div className="div">
        <h2>グローバル変数のSelector経由で取得！！！</h2>
        <div>
          <button onClick={() => setCounter(counter - 2)}>-</button>
          <span>{counter}</span>
          <button onClick={() => setCounter(counter + 2)}>+</button>
        </div>
      </div>
    </>
  )
})

export default Counter
```

触ってみると意外と素直なやつなんでした。


https://recoiljs.org/