Recoilを基礎から理解しよう！(環境構築・Atom編)

この記事は

- Reactで状態管理ツールを使ってみたい。
- でも学習コストが高くて難しそう。

そのように感じている人向けに、Recoilの使い方をまとめたものになっています。

- [Recoilを基礎から理解しよう！(環境構築・Atom編)](https://qiita.com/takusan64/items/bdb61b46d46395e913df):point_left_tone2: now
- [Recoilを基礎から理解しよう！(Selector編)](https://qiita.com/takusan64/items/b59458ca48df8e888458)　

筆者はReduxという類似ツールを使ったことがありますが、**「圧倒的にRecoilは簡単」**　だと思っています！
状態管理ツールの選定に迷っている人、`Recoil`の利用を考えてみてはいかがでしょうか！！

# Recoilってなに？

Reactの提供元であるMeta(FaceBook)が開発中の新しい状態管理ライブラリです。
ReduxやReactQueryの立ち位置のライブラリになります！

https://recoiljs.org/

2022年2月時点ではプレリリース状態（v0.6.1）となっていますが、作っているのがReactの生みの親ですので状態管理ライブラリとして標準利用される可能性大だと思っています。

# 実装
それでは早速書いていきましょう！

## まず初めに
Next.jsやRecoilなど必要なライブラリをインストールします。

まず最初に`Next.js`のインストール。

```sh
npx create-next-app nextjs-recoil
```

作成された`nextjs-recoilディレクトリ`の中身をルートディレクトリに持ってきます。
（ちょっと見栄えが悪いので..）

こんな感じに移動させてください！

```
.
├── LICENSE
├── README copy.md
├── README.md
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── pages
├── public
└── styles
```

今回のメインの`Recoil`をインストールします。

```sh
npm install --save recoil
```

## Recoilを有効化
Recoilは`RecoilRoot`で囲ったコンポーネント内で利用できます。
公式ではルートコンポーネントに配置するのを推奨しているようですので`/pages/_app.js`に配置しましょう。

```jsx:/pages/_app.js
import {　RecoilRoot　} from 'recoil';

function MyApp({ Component, pageProps }) {
  return (
    <RecoilRoot>
      <Component {...pageProps} />
    </RecoilRoot>
  )
}

export default MyApp
```

https://recoiljs.org/docs/introduction/getting-started#recoilroot

これだけの設定でRecoilを利用できるようになります！
（めちゃめちゃ簡単ですね...！）

`Next.js`を起動させましょう。

```sh
npm run dev
```

## Atomって何？
Recoilでは`Atom`という単位で、各状態の管理を行うことができます。
以下のような`Atom`を作成することで、異なるページ間の状態管理をすることができます。

**Atomの基本形**

```js
const todoState = atom({
  key: "todo", // 一位のキー名
  default: ["todo1"], // 初期値
});
```

- key: 作成したAtomに付与する一位のキー名（重複不可）
- default: Atomの初期値

https://recoiljs.org/docs/basic-tutorial/atoms/

## データを表示・更新させる

今回は簡単なTodoアプリを作成するので、Todoの状態を管理する`Atom`を作成します。
`/recoil/todo.js`に`Atom`を作成し、どのディレクトリでも利用できるよう`export`しておきましょう。

```js:/recoil/todo.js
import { atom } from "recoil";

//todo Atom
export const todoState = atom({
  key: "todo",
  default: ["todo1"]
});
```

先ほど作成した`Atom`を早速表示させましょう。
Recoilは基本的にReactHooksを用いて状態の操作を行います。
データを編集する場合は、`useRecoilState()`を利用します。

**useRecoilState()の基本形**

```js
//const [Atomの状態変数, Atomを更新する関数] = useRecoilState(対象のAtom)
const [todoList, setTodoList] = useRecoilState(todoState)
```

- 1つ目の要素： `Atom`の現在の値
- 2つ目の要素： `Atom`の現在の値を更新するための関数

今回はこのような形で`/pages/index.js`に実装します。

```jsx:/pages/index.js
import { useState } from "react"
import { useRecoilState } from "recoil";
import { todoState } from "../recoil/todo"

export default function Home() {
  // TodoのAtomを呼び出し
  const [todoList, setTodoList] = useRecoilState(todoState)

  const [todo, setTodo] = useState("")

  const handleChange = (e) =>{
    setTodo(e.target.value)
  }

  // Todoリストを更新する
  const pushTodo = (newTodo) => {
    setTodoList([...todoList, newTodo])
    setTodo("")
  }

  return (
    <div>
      <p>todo list</p>
      <ul>
        {todoList.length && todoList.map((v, i) => (
          <li key={i}>{v}</li>
        ))}
      </ul>
      <div>
        <input type="text" value={todo} onChange={handleChange} />
        <button onClick={() => pushTodo(todo)}>
          add Todo
        </button>
      </div>
    </div>
  )
}

```

[localhost:3000](localhost:3000) にアクセスするとTodoアプリができていると思います！

<img width="300" alt="gif1.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469819/a75dff4e-7f1b-f8a2-6f62-2f5862d93ee4.gif">

https://recoiljs.org/docs/api-reference/core/useRecoilState

[**Tips**]
Recoilには`useRecoilValue()`という**データ表示のみ**行うHooksと、`useSetRecoilState()`という**状態の更新のみ**を行うHooksも用意されています。
`useRecoilValue()`はあまり使わないかもですが、`useSetRecoilState()`は是非活用して欲しいです！
Reactのパフォーマンス向上には、データの再レンダリングを少なくすることが重要になります。
`useSetRecoilState()`を利用することで、不要なレンダリング防止に繋がります。
**状態の更新のみ**を行う場合は、積極的に使っていきましょう！！

```js
// Todo Atomのデータ表示のみを行う場合、こんな感じ
const todoList = useRecoilValue(todoState)
// Todo Atomのデータ更新のみを行う場合、こんな感じ
const setTodoList = useSetRecoilState(todoState)
```

https://recoiljs.org/docs/api-reference/core/useRecoilValue/

https://recoiljs.org/docs/api-reference/core/useSetRecoilState/

# 最後に
次回は`RecoilのSelector`について書きたいと思います！

今回利用したコードはこちらになります！（不要なファイルは削除してあります。）
https://github.com/takusan64/nextjs-recoil