Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

お魚リストを取得して一覧表示するコンポーネントの追加 #11

Merged
merged 16 commits into from
Jul 17, 2022

Conversation

yukinissie
Copy link
Collaborator

@yukinissie yukinissie commented Jul 12, 2022

resolved: #16

Reactでどうしてもお魚を釣りたい(意訳)

スクリーンショット 2022-07-13 18 00 38

単にReactからAPIを叩いてお魚データを取得するだけのソースコードです。

CosmosDB(データベース)

CosmosDBには以下のお魚データが入っています。

[
  {
    "pk": "fishes",
    "class": "shark",
    "name": {
      "japanese": "ネコザメ",
      "english": "Japanese bullhead shark",
      "katakana": "ジャパニーズブルヘッドシャーク"
    },
    "explanation": "ネコザメの名前の由来として言われているのが眼の上の骨のでっぱりです。眼の上の骨が隆起しているのでそれをネコの耳に見立ててネコザメと呼ばれています。",
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Heterodontus_japonicus1.jpg/375px-Heterodontus_japonicus1.jpg",
    "id": "d1d4a4ac-5a49-4d50-86e5-38829e4a8ddb",
    "_rid": "fwszAMtTxVsBAAAAAAAAAA==",
    "_self": "dbs/fwszAA==/colls/fwszAMtTxVs=/docs/fwszAMtTxVsBAAAAAAAAAA==/",
    "_etag": "\"1e002cca-0000-2300-0000-62cd588e0000\"",
    "_attachments": "attachments/",
    "_ts": 1657624718
  },
  {
    "pk": "fishes",
    "class": "shark",
    "name": {
      "japanese": "シマネコザメ",
      "english": "Zebra bullhead shark",
      "katakana": "ゼブラブルヘッドシャーク"
    },
    "explanation": "体表面には独特な縞模様があり、白色地に22-36の暗色横帯が入ることで他のネコザメ類と区別できる。",
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Zebra_bullhead_shark_Beijing_Aquarium_17_Sep_2010.jpg/375px-Zebra_bullhead_shark_Beijing_Aquarium_17_Sep_2010.jpg",
    "id": "8f867a66-431f-4b8b-9945-623bacbe47b7",
    "_rid": "fwszAMtTxVsCAAAAAAAAAA==",
    "_self": "dbs/fwszAA==/colls/fwszAMtTxVs=/docs/fwszAMtTxVsCAAAAAAAAAA==/",
    "_etag": "\"0501c689-0000-2300-0000-62ce604e0000\"",
    "_attachments": "attachments/",
    "_ts": 1657692238
  },
  {
    "pk": "fishes",
    "class": "shark",
    "name": {
      "japanese": "ヒゲツノザメ",
      "english": "Mandarin dogfish",
      "katakana": "マンダリンドッグフィッシュ"
    },
    "explanation": "吻の先端近くには特徴的なヒゲが1対あります。また,第1背鰭と第2背鰭の基部に白色の棘がそれぞれ1本ずつありそれらが名前の由来となっている。",
    "imageUrl": "https://cdn-ak.f.st-hatena.com/images/fotolife/i/itsuwalove777/20201026/20201026042113.jpg",
    "id": "f7f47bf6-ae96-4f4b-9399-633a353a941c",
    "_rid": "fwszAMtTxVsDAAAAAAAAAA==",
    "_self": "dbs/fwszAA==/colls/fwszAMtTxVs=/docs/fwszAMtTxVsDAAAAAAAAAA==/",
    "_etag": "\"05018efe-0000-2300-0000-62ce60630000\"",
    "_attachments": "attachments/",
    "_ts": 1657692259
  }
]

Node.js(バックエンド)

api/FishesRead/index.ts

import { AzureFunction, Context, HttpRequest } from '@azure/functions'

const httpTrigger: AzureFunction = async function (
  context: Context,
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  req: HttpRequest
): Promise<void> {
  context.res.json(context.bindings.documents)
}

export default httpTrigger

CosmosDBからcontext.bindings.documentsを介してfishesのデータを全て取得しています。

api/FishesRead/function.json

context.bindings.documentsの定義はapi/FishesRead/function.jsonbindingsの中にあります。

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get"],
      "route": "fishes"
    },
    {
      "name": "documents",
      "type": "cosmosDB",
      "direction": "in",
      "databaseName": "CosmosDB",
      "collectionName": "Fishes",
      "sqlQuery": "SELECT * from c WHERE c.pk = 'fishes'",
      "connectionStringSetting": "CosmosDBConnection"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ],
  "scriptFile": "../dist/FishesRead/index.js"
}

実際にCosmosDBとやり取りするためにはapiディレクトリにlocal.settings.jsonを置く必要があります。内容は @yukinissie に聞いてください。シークレットなファイルになります。

React(フロントエンド)

src/components/Fishes.tsx

お魚データを取得中はローディングコンポーネントを表示します。

import { FishList } from '@/components/FishList'
import { Loading } from '@/components/Loading'
import { useFetch } from '@/hooks/useFetch'
import { Fish } from '@/types/Fish'

export const Fishes = () => {
  const { data, isLoading, isError } = useFetch<Array<Fish>>('/api/fishes')

  if (isError) {
    return <div>エラーが発生しました。。</div>
  }

  if (!data || isLoading) {
    return <Loading />
  }

  return <FishList fishes={data} />
}

src/hooks/useFetch.ts

useFetchこの記事をめちゃくちゃ参考にしました。

import { useEffect, useState } from 'react'

/**
 * 任意の型のデータをAPIから取得するためのカスタムフックです。
 * Array<Fish>型のjsonデータを/api/fishesから取りたい場合は
 * const { data, isLoading, isError } = useFetch<Array<Fish>>('/api/fishes')
 * をコンポーネントの中で最初に呼びます。
 */
export const useFetch = <T>(url: string) => {
  const [data, setData] = useState<T>()
  const [isLoading, setLoading] = useState(true)
  const [isError, setError] = useState(false)

  useEffect(() => {
    // eslint-disable-next-line @typescript-eslint/no-extra-semi
    ;(async () => {
      try {
        const res = await fetch(url)
        const data = await res.json()
        setData(data)
      } catch (err) {
        console.log(err)
        setError(true)
      } finally {
        setLoading(false)
      }
    })()
  }, [])

  return { data, isLoading, isError }
}

src/types/Fish.ts

APIがどのような値を返すことを期待しているかこのファイルで宣言しています。

type PK = 'fishes'

type Class = 'fish' | 'shark' | 'mammalian'

type Name = {
  japanese: string
  english: string
  katakana: string
}

export type Fish = {
  id: string
  pk: PK
  class: Class
  name: Name
  explanation: string
  imageUrl: string
}

src/componets/FishList.tsx

ちなみに表示に使用するFishListコンポーネントはこのようなコードになっています。

import { Fish } from '@/types/Fish'

interface Props {
  fishes: Array<Fish>
}

export const FishList = (props: Props) => {
  const fishItems = props.fishes.map((fish) => (
    <li key={fish.id}>
      <p>ID: {fish.id}</p>
      <p>プライマリーキー: {fish.pk}</p>
      <p>分類: {fish.class}</p>
      <p>日本語名: {fish.name.japanese}</p>
      <p>英語名: {fish.name.english.value}</p>
      <p>カタカナ: {fish.name.katakana}</p>
      <p>解説: {fish.explanation}</p>
      <img src={fish.imageUrl} />
    </li>
  ))

  return <ul>{fishItems}</ul>
}

受け取ったお魚データの数だけリストにして返しているだけです。

@yukinissie yukinissie self-assigned this Jul 12, 2022
@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@yukinissie yukinissie changed the title お魚リストを取得して一覧表示するコンポーネントの追加 WIP: お魚リストを取得して一覧表示するコンポーネントの追加 Jul 13, 2022
@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@yukinissie yukinissie changed the title WIP: お魚リストを取得して一覧表示するコンポーネントの追加 お魚リストを取得して一覧表示するコンポーネントの追加 Jul 13, 2022
@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@github-actions
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://kind-smoke-0c29e3100-11.eastasia.1.azurestaticapps.net

@takatoshiinaoka takatoshiinaoka merged commit 2f25ea9 into main Jul 17, 2022
@takatoshiinaoka takatoshiinaoka deleted the feature/add-get-fishes branch July 17, 2022 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

最初のPR(プルリクエスト)をマージする
2 participants