Open6
Vite + React + GraphQL + TanStack(React Query, React Location) 素振り
Vite
Vite プロジェクトを作成
yarn create vite
ライブラリは React(ts) を選択
? Select a framework: › - Use arrow-keys. Return to submit.
vanilla
vue
❯ react
preact
lit
svelte
起動
yarn && yarn dev
ready in 734ms.
早い。
React Query
インストール
yarn add react-query
App.tsx を編集
import { QueryClient, QueryClientProvider } from 'react-query'
const queryClient = new QueryClient()
function App() {
return (
<QueryClientProvider client={queryClient}>
<>App.tsx</>
</QueryClientProvider>
)
}
export default App
GraphQL
graphql と graphql codegen の準備をする。
@graphql-codegen/typescript-react-query
というpackageを使って types と hooks を自動生成する。(codegen ドキュメントのデザインが変わっていてびっくりした)
インストール
yarn add @graphql-codegen/cli @graphql-codegen/typescript-react-query @graphql-codegen/typescript-operations graphql graphql-request
codegen.yml
fetch hooks の設定
GraphQL API には SpaceX のAPI endpoint を使用してみる。
overwrite: true
schema:
- https://api.spacex.land/graphql/
documents:
- ./src/**/*.graphql
- ./src/**/*.graphql
generates:
./src/generated/index.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-query
config:
fetcher: graphql-request
generate
graphql-codegen -r --config codegen.yml
src/generated/index.ts にファイルが生成される。
生成された fetcher hooks を使う
function App() {
return (
<QueryClientProvider client={queryClient}>
<Component />
</QueryClientProvider>
)
}
const Component = () => {
const { data, isLoading, isError } = useLaunchesPastQuery(client)
if (isLoading) return <>Loading...</>
if (isError) return <>Error(:</>
return (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', width: "100%", height: '100vh'}}>
<div>
{data?.launchesPast?.map(launch => (
<div key={launch?.mission_name}>
<div style={{ marginBottom: '8px' }}>
<p style={{ margin:0 }}>Mission name: {launch?.mission_name}</p>
<p style={{ margin:0 }}>Launch date: {launch?.launch_date_local}</p>
</div>
</div>
))}
</div>
</div>
)
}
無事データを取得できた(めちゃくちゃ見辛い...
React Location
インストール
yarn add react-location
セットアップ
import { Link, MakeGenerics, Outlet, ReactLocation, Route, Router, useMatch } from "react-location";
const location = new ReactLocation();
const routes: Route[] = [
{
path: "/",
element: 'This is Home',
},
{
path: "/launches",
element: <Component />
}
]
function App() {
return (
<QueryClientProvider client={queryClient}>
<Router routes={routes} location={location}>
<div style={{ maxWidth: '960px', margin: '0 auto' }}>
<h2>SpaceX Launches</h2>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/launches">Launches list</Link></li>
</ul>
<Outlet />
</div>
</Router>
</QueryClientProvider>
)
}
いい感じに遷移 and データの取得が出来てそう
休憩。この後 Loader を試す。
React Location の Route loader を使う
Route loader を使うことで preload を実装することができる。
route の定義すオブジェクト内で実装するため、先ほど作った fetcher hooks は使えない。
新たにroute preload 用の fetcher を graphql-request で生成する。
yarn add graphql-request
codegen.yml の更新
overwrite: true
schema:
- https://api.spacex.land/graphql/
documents:
- ./src/**/*.graphql
- ./src/**/*.graphql
generates:
./src/generated/index.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-query
config:
fetcher: graphql-request
# 追加
./src/generated/routes/index.ts:
plugins:
- typescript
- typescript-operations
- typescript-graphql-request
生成された sdk をつかって loader を実装する
const sdk = getSdk(client)
function App() {
const routes: Route<LocationGenerics>[] = [
{
path: "/",
element: 'This is Home',
},
{
path: "/launches",
element: <Component />,
loader: async () => {
const { launchesPast } = await sdk.LaunchesPast()
return {
launchesPast: {
data: launchesPast
}
}
}
}
]
Router にキャッシュの期間を指定
<Router routes={routes} location={location} defaultLinkPreloadMaxAge={1000}>
....
</Router>
Hover時に preload しているため、高速な遷移が実現できている。