【GraphQL】フロントエンドでGraphQLを接続する
GraphQL

【GraphQL】フロントエンドでGraphQLを接続する

作成日:2021年11月26日
更新日:2021年11月27日

前回は、Prisma を使って、ログイン機能を追加しました。

graphql-prisma-login

【GraphQL】Prismaを使って、ログイン機能を追加する

今回は、バックエンドで作成した GraphQL を、フロントエンドで接続します。

バックエンドのコードは、こちらです。

フロントエンドのテンプレートは、React と MUI で作成しました。

GraphQL を接続するために、React に GraphQL と Apollo Client をインストールします。

ターミナルで、npm install --save graphql @apollo/clientを実行しましょう。

GraphQL と Apollo Client がインストール完了した後、index.tsx に ApolloClient と ApolloProvider、InMemoryCache をインポートします。

ts
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";

ApolloClientで、バックエンドの URI と、キャッシュを設定します。

バックエンドの URI は http://localhost:4000/graphql、キャッシュは先程インポートした、InMemoryCacheを指定します。

tsx
const client = new ApolloClient({
uri: "http://localhost:4000/graphql",
cache: new InMemoryCache(),
});

url ではなく、uri なので、注意しましょう。

<App />ApolloProviderでラップします。

client を指定しなければいけないので、先程作成したclientを指定します。

tsx
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);

これで、GraphQL を接続する準備が完了したので、実際にデータを取得してみます。

pages フォルダの Book.tsx を開きます。

Apollo Client から gql と useQuery をインポートします。

tsx
import { gql } from "@apollo/client";

gql で、取得したいクエリの雛形を作ります。

gql の中身は、バッククォートで囲みます。

tsx
const booksData = gql``;

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

image2

isRead が波線になっているので、バックエンドの schema.ts のtype BookisReadを追加します。

ts
type Book {
id: Int!
title: String!
author: String!
createdAt: String!
category: Category!
isRead: Boolean!
}

では、GraphQL に戻って、allBooks ボタンをクリックすると、

image3

本のデータを取得することができます。

今作成した、GraphQL をコピーして、フロントエンドのgql内に貼り付けます。

tsx
const booksData = gql`
query allBooks {
books {
id
title
author
category {
name
}
isRead
createdAt
}
}
`;

次に、useQueryをインポートします。

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

useQuery を使って、先程作成したbooksDataからdataを取り出します。

tsx
const { data } = useQuery(booksData);

アドレスは http://localhost:3000/book を指定して、console.log()で確認すると、

image4

GraphQL のデータを取得できているのがわかります。

data を使って、books のデータをブラウザに表示させてみます。

data から books を取り出します。

tsx
const { books } = data;

books を map で展開します。

tsx
<TableBody>
{books.map((book) => (
<TableRow key={book.id}>
<TableCell>{book.id}</TableCell>
<TableCell>{book.title}</TableCell>
<TableCell>{book.author}</TableCell>
<TableCell>{book.category.name}</TableCell>
<TableCell>{book.isRead}</TableCell>
<TableCell>{book.createdAt}</TableCell>
</TableRow>
))}
</TableBody>

book の型を指定します。

tsx
type TypeBook = {
id: number;
title: string;
author: string;
category: {
name: string;
};
isRead: boolean;
createdAt: string;
};
tsx
<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>
<TableCell>{book.isRead}</TableCell>
<TableCell>{book.createdAt}</TableCell>
</TableRow>
))}
</TableBody>

一度、ブラウザで確認すると、

image5

エラーが発生しました。

これは、GraphQL のデータを取得するより、React のレンダリングする方が早いので、エラーになりました。

エラーが発生しないように、データを取得するまでローディングします。

useQueryloadingを追加します。

tsx
const { data, loading } = useQuery(booksData);

loading が発生しているときは、メッセージを表示するようにします。

tsx
if (loading) return <div>Loading...</div>;

では、サイド確認すると、

image6

image7

ローディングが発生した後、books のデータを表示することができました。

createDataは、必要ないので、削除します。

今のところ、読了欄には、何も表示されていません。

isRead が true の場合『済』、false の場合『未』を表示します。

tsx
<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>{book.createdAt}</TableCell>
</TableRow>
))}
</TableBody>

image8

無事、表示されました。

また、作成日も数字の羅列なので、修正します。

tsx
<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>
</TableRow>
))}
</TableBody>

image9

GraphQL が誤っている場合、エラーメッセージを表示するようにします。

useQueryで、errorを取得します。

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

loadingと同様に、errorがある場合の表示を設定しましょう。

tsx
if (error) return <div>データを取得することができませんでした</div>;

試しに、gqlididdにしてみると、

image10

エラーメッセージを表示することができました。

全文は、以下の通りです。

フロントエンド:

バックエンド:

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

graphql-client-detail

【GraphQL】フロントエンドで詳細画面へ遷移する

© 2024あずきぱんウェブスタジオ