前回は、フロントエンドでGraphQLを接続しました。

今回は、GraphQLで接続したデータ一覧から、詳細画面へ遷移します。

コードは、以下の通りです。

フロントエンド:

バックエンド:

まずは、詳細画面を作成しましょう。

pagesフォルダに、BookDetail.tsxを作成します。

中身は、MUIのカードを使って作成します。

https://mui.com/components/cards/

また、isReadcreatedAtは、Book.tsxをコピーします。

import * as React from "react";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";

export default function BookDetail() {
  return (
    <Card sx={{ minWidth: 275 }} variant="outlined">
      <CardContent>
        <Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
          ID:{book.id}
        </Typography>
        <Typography variant="h5" component="div">
          タイトル:{book.title}
        </Typography>
        <Typography sx={{ mb: 1.5 }} color="text.secondary">
          著者:{book.author}
        </Typography>
        <Typography variant="body2" sx={{ mb: 1.5 }}>
          カテゴリ:{book.category.name}
        </Typography>
        {book.isRead ? (
          <Typography variant="body2" sx={{ mb: 1.5 }}>
            読了:済
          </Typography>
        ) : (
          <Typography variant="body2" sx={{ mb: 1.5 }}>
            読了:未
          </Typography>
        )}
        <Typography variant="body2">
          作成日:
          {`${new Date(Number(book.createdAt))}`
            .split(" ")
            .splice(1, 3)
            .join(" ")}
        </Typography>
      </CardContent>
    </Card>
  );
}

App.tsxで、ルート処理をします。

book/:id画面で、bookのデータが表示されないように、path="/book"の前にexactを追加します。

<Route exact path="/book">
  <Dashboard>
    <Book />
  </Dashboard>
</Route>
<Route path="/book/:id">
  <Dashboard>
    <BookDetail />
  </Dashboard>
</Route>

バックエンドのgraphqlに移動して、bookでデータを取得してみましょう。

image2

こちらのSingleBookの内容をコピーします。

query SingleBook($bookId: Int!) {
  book(id: $bookId) {
    id
    title
    author
    category {
        name
      }
    isRead
    createdAt
  }
}

BookDetail.tsxに戻ります。

gql,とuseQueryをインポートします。

import { gql, useQuery } from "@apollo/client";

gqlを作成し、先程コピーしたGraphQLを貼り付けます。

const bookData = gql`
  query SingleBook($bookId: Int!) {
    book(id: $bookId) {
      id
      title
      author
      category {
        name
      }
      isRead
      createdAt
    }
  }
`;

遷移したいデータのidを取得するために、useParamsをインポートします。

import { useParams } from "react-router-dom";

では、idを取得しましょう。

const { id } = useParams<{ id?: string | undefined }>();

Book.tsxと同様に、useQueryで、dataerrorloadingを設定します。

const { data, error, loading } = useQuery(bookData);

if (error) return <div>error page</div>;

if (loading) return <div>Spinner...</div>;

const { book } = data;

bookidと遷移したいデータidを紐づけるため、useQueryのオプションで、variablesを設定します。

指定するのは、bookdatabookIduseParamsidです。

idはstring型なので、number型へ変換します。

const { data, error, loading } = useQuery(bookData, {
  variables: {
    bookId: Number(id),
  },
});

では、試しにurlでhttp://localhost:3000/book/1を入力し、アクセスしてみます。

image3

idが『1』のデータを表示することができました。

Book.tsxで、詳細画面へ遷移するリンクを作成しましょう。

return (
  <React.Fragment>
    <Title>読書リスト</Title>
    <Table size="small">
      <TableHead>
        <TableRow>
          <TableCell>ID</TableCell>
          <TableCell>タイトル</TableCell>
          <TableCell>著者</TableCell>
          <TableCell>カテゴリ</TableCell>
          <TableCell>読了</TableCell>
          <TableCell>作成日</TableCell>
          <TableCell></TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {books.map((book: TypeBook) => (
          <TableRow key={book.id}>
            <TableCell>{book.id}</TableCell>
            <TableCell>{book.title}</TableCell>
            <TableCell>{book.author}</TableCell>
            <TableCell>{book.category.name}</TableCell>
            {book.isRead ? (
              <TableCell>済</TableCell>
            ) : (
              <TableCell>未</TableCell>
            )}
            <TableCell>
              {`${new Date(Number(book.createdAt))}`
                .split(" ")
                .splice(1, 3)
                .join(" ")}
            </TableCell>
            <TableCell>
              <Link href={`/book/${book.id}`} underline="hover">
                詳細画面
              </Link>
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  </React.Fragment>
);

image4

IDが2の『詳細画面』をクリックすると、

image5

正しく画面が遷移しました。

フロントエンドのコード内容は、こちらです。

次回は、フロントエンドでGraphQLのデータを追加します。

ブログ一覧