React18のsuspenseとreact-error-boundaryとTanStack Queryを使う @yukilulu0229

https://ja.react.dev/reference/react/Suspense

<Suspense> を使うことで、子要素が読み込みを完了するまでフォールバックを表示させることができます。

```
<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>
```

参考 @nuko-suke

https://qiita.com/nuko-suke/items/fdecac831533c3d8bbf0

https://zenn.dev/hakoten/articles/f5b577d8b63a4a

## react-error-boundary

https://www.npmjs.com/package/react-error-boundary

```
npm i react-error-boundary
```

## 使い方

### 準備

TanStack Queryと組み合わせる

https://tanstack.com/query/latest

```
npm i @tanstack/react-query
```

https://tanstack.com/query/latest/docs/framework/react/installation


### コード


```main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
    },
  },
})

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>,
)

```

```
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
    },
  },
})
```

new して変数に入れる

```
<QueryClientProvider client={queryClient}>
  <App />
</QueryClientProvider>
```

- QueryClientProviderで囲む
- client={queryClient}する

```App.tsx
import {Suspense, useState} from "react";
import ReactQuery from "./components/ReactQuery.tsx";

function App() {
  return (
    <main style={{display: "flex", justifyContent: "center"}}>
      <div style={{flex: 1}}>
        <ErrorBoundary fallback={<p>エラーです</p>}>
          <Suspense fallback={<p>ローディング中</p>} >
            <ReactQuery />
          </Suspense>
        </ErrorBoundary>
      </div>
    </main>
  )
}

export default App

```

```
<Suspense fallback={<p>ローディング中</p>} >
  <ReactQuery />
</Suspense>
```

```<Suspense fallback={<p>ローディング中</p>} >```
で囲ってfallbackにロード中のコンポーネントを入れる

```<ErrorBoundary fallback={<p>エラーです</p>}>```

で囲ってエラーのときの処理をコンポーネントに入れる


```ReactQuery.tsx
import React from 'react';
import AlbumList from "./AlbumList.tsx";
const ReactQuery = () => {
  return (
    <>
      <p>ReactQuery</p>
      <div style={{flexGrow: 1}}>
        <AlbumList />
      </div>
    </>
  );
};

export default ReactQuery;

```

```AlbumList.tsx
import {useQuery} from "@tanstack/react-query";
import axios from "axios";
import React from 'react';

type Album = {
  userId: number,
  id: number,
  title: string
}


const fetchAlbums = async () => {
  const result = await axios.get<Album[]>("https://jsonplaceholder.typicode.com/albums");

  return result.data
}

const AlbumList = () => {
  const {data} = useQuery<Album[]> ({
    queryKey: ["album"],
    queryFn: fetchAlbums
  });

  return (
    <div style={{height: "300px", border: "2px solid gray", background: "cornsilk", overflowY: "scroll"}}>
      <p>AlbumList</p>
      {data && data.map((album) => <p key={album.id}>{album.id}:{album.title}</p>)}
    </div>
  );
};

export default AlbumList;

```

https://tanstack.com/query/v5/docs/framework/react/reference/useQuery

https://tanstack.com/query/v5/docs/framework/react/guides/query-keys

https://tanstack.com/query/v5/docs/framework/react/guides/query-functions#queryfunctioncontext

## その他

https://swr.vercel.app/ja/docs/suspense

SWRがvercelだが2024-02-13では

React はまだサスペンスをデータ取得フレームワークである SWR などで使うことを 推奨していません (詳細)。 これらの API は将来的に私たちの調査により変更される可能性があります。

となっている


## 読み込み時間をわざと遅らせる関数

```App.tsx
const sleep = (ms: number):Promise<any> => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  })
}

const fetchAlbums = async () => {
  const result = await axios.get<Album[]>("https://jsonplaceholder.typicode.com/albums").then(await sleep(5000));

  return result.data
}
```