ReactのRecoilでAPIデータ(非同期処理のデータ)を取得する。(Hands-on)

## はじめに
APIを始めとする非同期処理の値を取得して、Recoilで状態管理する記事です。同期処理に関しては、[以前の記事](https://qiita.com/kouji0705/items/9f07e1e3f55173ec659c)に記載しておりますので、ご参考にしてください。

## Hands-onスタート
完成イメージを貼っておきます。例の如く、APIの連動先は[JSONPlaceholder](https://jsonplaceholder.typicode.com/)です。
![スクリーンショット 2022-06-24 22.18.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/df700113-fe22-01ea-b75f-60700b2cef75.png)

```shell:プロジェクト作成
yarn create react-app recoil_async --template typescript
yarn add recoil
```


```ディレクトリ構成
~/develop/react/recoil/recoil_async $ 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　　　　　　←修正
│   ├── User.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
```

```json:package.json
{
  "name": "recoil_async",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^13.0.0",
    "@testing-library/user-event": "^13.2.1",
    "@types/jest": "^27.0.1",
    "@types/node": "^16.7.13",
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0",
    "axios": "^0.27.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "recoil": "^0.7.4",
    "typescript": "^4.4.2",
    "web-vitals": "^2.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
```


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

```tsx:App.tsx
import React, { Suspense } from 'react';
import './App.css';
import { RecoilRoot } from 'recoil'
import User from './User'

// 値取得中のローディング処理
const Fallback = () => {
  return (
    <div id="load">
      <span>Loading...</span>
    </div>
  )
}

function App() {

  return (
    <div>
      <RecoilRoot>
          <Suspense fallback={<Fallback />}>
          <div>
          <User/>
          </div>
        </Suspense>
      </RecoilRoot>
    </div>
  );
}

export default App;

```
→Pointは２点
1. `RecoilRoot`で囲う。(Recoilを使う場合は囲う必要があります。)
2. `Suspense`の処理を入れる。非同期処理のため、ローディング中の対応を入れておきます。

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

export const UserInfo =selector({
    key:'UserInfo',
    get: async ({get})=>{
        const response = await axios.get<UserType>("https://jsonplaceholder.typicode.com/todos/1")
        return response.data
    }
})

type UserType ={
    userId:number
    id:number
    title:string
    completed:boolean
}

```
→ココのポイントはgetの後ろに`async`をつけるところ。他は特に変わらないですね。

```tsx:User.tsx
import { FC, memo } from "react"
import { useRecoilValue } from "recoil"
import { UserInfo } from "./atom"

const User: FC = memo(()=>{
    const user = useRecoilValue(UserInfo);
    return (
    <>
    <div className="div">
        <h2>ID：{user.id}</h2>
        <h2>ユーザID：{user.userId}</h2>
        <h2>タイトル：{user.title}</h2>
    </div>
    <div></div>
    </>
    )
})

export default User
```