はじめに
APIを始めとする非同期処理の値を取得して、Recoilで状態管理する記事です。同期処理に関しては、以前の記事に記載しておりますので、ご参考にしてください。
Hands-onスタート
完成イメージを貼っておきます。例の如く、APIの連動先はJSONPlaceholderです。
プロジェクト作成
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
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"
]
}
}
ソースコードの中身
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は2点
-
RecoilRoot
で囲う。(Recoilを使う場合は囲う必要があります。) -
Suspense
の処理を入れる。非同期処理のため、ローディング中の対応を入れておきます。
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
をつけるところ。他は特に変わらないですね。
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