react-fetching-library で Suspense 使ってみた。

最近ReactでAPIからデータフェッチする際に`useEffect`を使っていましたが、
これを読んだあと、これからは`Suspense`を積極的に使っていこうと思い立ちました。
https://overreacted.io/ja/a-complete-guide-to-useeffect/

そんな自分にタイムリーなパッケージ、4日前(投稿日現在)に出来立てホヤホヤの
`react-fetching-library`を発見。
早速使ってみたいと思います！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501763/77f8aaf3-4b18-ae71-3a8b-717982337253.png)
https://marcin-piela.github.io/react-fetching-library/#/?id=usesuspensequery


# Suspense使用前

ポートフォリオに投稿したQiitaの記事を載せるために、こんな感じで実装していました。
レンダリングしている内容は省略します🙇‍♂️

```jsx:App.js
import React from 'react'
import Writing from 'sections/Writing'

export default () => {
  return (
    <div>
      <Writing />
    </div>
  )
}
```

```js:sections/Writing.js

import React, { useState, useEffect } from 'react'
import { fetchQiitaArticles } from 'lib/api'

export default () => {
  const [articles, setArticles] = useState([])

  useEffect(() => {
    const handleGetArticles = response => {
      setArticles(response)
    }
    fetchQiitaArticles({ handleGetArticles })
  }, [])

  return (
    // fetchしたarticlesを使ってレンダリング
  )
}
```

```js:lib/api.js
export const fetchQiitaArticles = async props => {
  const { handleGetArticles } = props
  await fetchGet({
    auth: process.env.REACT_APP_QIITA_AUTH,
    url: 'https://qiita.com/api/v2/authenticated_user/items',
    successAction: handleGetArticles,
  })
}

const fetchGet = async props => {
  const { auth, url, successAction, failureAction } = props

  return await fetch(url, {
    headers: {
      Authorization: `Bearer ${auth}`,
    },
  })
    .then(response => response.json())
    .then(responseJson => {
      // console.log(responseJson)
      if (successAction) {
        successAction(responseJson)
      }
    })
    .catch(error => {
      // console.error(error)
      if (failureAction) {
        failureAction()
      }
    })
}
```

# セットアップ
まずは `react-fetching-library`をインストールします。

```zsh

$ yarn add react-fetching-library
```

続いて`Client`の作成します。
とりあえず今回はオプションなし。

```js:api/Client.js
import { createClient } from 'react-fetching-library'
export const Client = createClient()
```
そして`<ClientContextProvider>`でAppを囲います。

```jsx:App.js
import React from 'react'
import { ClientContextProvider } from 'react-fetching-library'
import { Client } from 'api/Client'
import Writing from 'sections/Writing'

export default () => {
  return (
    <ClientContextProvider client={Client}>
      <Writing />
    </ClientContextProvider>
  )
}
```


これで、`react-fetching-library`の機能が使用可能になりました！

# fetchの用意
`react-fetching-library`で使用する`GET`メソッドを作成します。

```js:api/fetchMyQiitaArticles.js
export const fetchMyQiitaArticles = {
  method: 'GET',
  endpoint: 'https://qiita.com/api/v2/authenticated_user/items',
  headers: {
    Authorization: `Bearer ${process.env.REACT_APP_QIITA_AUTH}`,
  },
}
```

# コンポーネントのラップ
`useEffect`を廃止して`WritingContainer`でラップします。
その際、`useSuspenseQuery`を使ってデータフェッチを行うようにします。

```jsx:container/WiritingContainer.js
import React from 'react'
import { useSuspenseQuery } from 'react-fetching-library'
import { fetchMyQiitaArticles } from 'api/fetchMyQiitaArticles'
import Writing from 'sections/Writing'

export default () => {
  const { payload, error, query } = useSuspenseQuery(fetchMyQiitaArticles)

  return <Writing error={error} articles={payload} />
}
```

```sections/Writing.js
import React, { useState, useEffect } from 'react'
import { fetchQiitaArticles } from 'lib/api'
 
export default props => {
  const { articles, error } = props

  return (
    // fetchしたarticlesを使ってレンダリング
  )
}
```

# Suspenseを使う！
```jsx:App.js
import React, { Suspense } from 'react'
import { ClientContextProvider } from 'react-fetching-library'
import { Client } from 'api/Client'
import WritingContainer from 'container/WritingContainer'

export default () => {
  return (
    <ClientContextProvider client={Client}>
      <Suspense fallback={<p>Loading ...</p>}>
        <WritingContainer />
      </Suspense>
    </ClientContextProvider>
  )
}
```

かなりアバウトになりましたが、
これでSuspenseを使ったデータフェッチができました 🎉

# おわりに
とりあえず自分は`useEffect`を使わずにデータフェッチができるようになりました。
`Suspense`界隈のリリース情報はしっかり追っていきたいですね。
あと`react-fetching-library`の公式Docが`TypeScript`で説明されていたので、
`TypeScript`での開発のモチベーションになりそうです。

# 参考
https://marcin-piela.github.io/react-fetching-library/#/?id=usage