質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

GraphQL

GraphQL は、アプリケーション・プログラミング・インタフェース (API) 向けのクエリ言語およびサーバーサイドランタイムです。APIの速度、柔軟性、開発者にとっての使いやすさを向上させるために設計され、データを複数のデータソースから取得するリクエストを1つのAPI呼び出しで構成できます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

1364閲覧

Next.js x graphql x urql を使ってクライアントサイドでデータ取得&表示

TatsuyaOkawa

総合スコア29

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

GraphQL

GraphQL は、アプリケーション・プログラミング・インタフェース (API) 向けのクエリ言語およびサーバーサイドランタイムです。APIの速度、柔軟性、開発者にとっての使いやすさを向上させるために設計され、データを複数のデータソースから取得するリクエストを1つのAPI呼び出しで構成できます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2023/07/29 06:59

編集2023/07/29 07:08

実現したいこと

  • Next.jsgraphqlurqlを使用したシンプルコードをvercelにデプロイしてエラーなく動かしたい
  • urqlsuspenseを用いて ロード中の描画を行いたい

前提

Next.jsのapp routerを用いて上記実現したいことができるかどうかを試しています。
いろいろとエラーが出ながら修正して進めていましたがよくわからない現象にぶつかりました。

componentの中でuseQuery(urql)を用いてfetchを行なってデータを表示したいのですが、なぜかデータを取得する際に以下のようなエラーが表示されます。

Error: There was an error while hydrating this Suspense boundary. Switched to client rendering.

これ以上の内容がないので分からないのですが、私の認識では最初からclient renderingをしているつもりだったのでどうしてこのタイミングでエラーが発生して Switched to client renderingされるのかが全く分かっていません。
どこか設定がおかしくてサーバーとクライアントの切り分けができていないのでしょうか?
それとも根本的なところで認識がおかしかったりするのでしょうか?

上記のエラーにはどう対応したら良いのでしょうか?
考え方などでも構いませんので教えていただけると非常に助かります。

該当のソースコード

少し多くなるかもですが、ご容赦ください

app/layout.tsx

1import { 2 UrqlProvider, 3 cacheExchange, 4 createClient, 5 debugExchange, 6 fetchExchange, 7 ssrExchange, 8} from "@urql/next"; 9import { devtoolsExchange } from "@urql/devtools"; 10import { refocusExchange } from "@urql/exchange-refocus"; 11import { retryExchange } from "@urql/exchange-retry"; 12 13const isServerSide = typeof window === "undefined"; 14const ssr = ssrExchange({ 15 isClient: !isServerSide, 16}); 17 18const client = createClient({ 19 url: "http://localhost:3000/api/graphql", 20 exchanges: [ 21 devtoolsExchange, 22 refocusExchange(), 23 cacheExchange, 24 retryExchange({}), 25 debugExchange, 26 fetchExchange, 27 ssr, 28 ], 29 requestPolicy: "cache-first", 30 fetchOptions: () => { 31 return { 32 headers: { authorization: "Bearer token" }, 33 credentials: "include", 34 }; 35 }, 36 suspense: true, 37}); 38 39export default function RootLayout({ 40 children, 41}: { 42 children: React.ReactNode; 43}) { 44 return ( 45 <html lang="ja"> 46 <body> 47 <UrqlProvider client={client} ssr={ssr}> 48 {children} 49 </Providers> 50 </body> 51 </html> 52 ); 53}

app/page.tsx

1import Component from "./components/Main"; 2 3export default async function page() { 4 return <Component />; 5}

app/components/Component.tsx

1const Component: React.FC<Props> = ({ query }) => { 2 return ( 3 <> 4 <Suspense fallback={<>ロード中</>}> 5 <FetchData /> 6 </Suspense> 7 </> 8 ); 9}; 10 11// ここから下はfetchするコンポーネント 12const dataQuery = ` 13 query ALL_BOOKS { 14 books { 15 title 16 page 17 } 18 } 19` 20const FetchData: React.FC = () => { 21 const [{ data }] = useQuery({ 22 query: dataQuery, 23 variables: {}, 24 context: { 25 suspense: true, 26 }, 27 }); 28 return ( 29 <> 30 {data.books.map((book) => ( 31 <div key={book.title}>{book.title}</div> 32 ))} 33 </> 34 ); 35};

pages/api/graphql.ts

1import { readFileSync } from "fs"; 2import { join } from "path"; 3import { startServerAndCreateNextHandler } from "@as-integrations/next"; 4import { ApolloServer } from "@apollo/server"; 5 6const typeDefs = readFileSync( 7 join(process.cwd(), "apollo/documents/schema.gql"), 8 "utf-8" 9); 10 11const resolvers = { 12 Query: { 13 books: () => { 14 return new Promise((resolve) => { 15 setTimeout(() => { 16 return resolve([ 17 { title: "タイトル1", page: 100 }, 18 { title: "タイトル2", page: 200 }, 19 { title: "タイトル30", page: 300 }, 20 ]); 21 }, 1000); 22 }); 23 }, 24 }, 25}; 26const apolloServer = new ApolloServer<Resolvers>({ typeDefs, resolvers }); 27export default startServerAndCreateNextHandler(apolloServer);

補足情報(FW/ツールのバージョンなど)

  • graphqlは pages/api/graphql.tsapollo-serverを用いて実装しています。
  • 特にサーバーの実装はしていないのでmockとして定数を返しています。

その他必要な情報があればコメント追記しますのでコメントいただければと思います。
何卒、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

詳しいところまでは分からなかったけどexchangesが今いことやってくれていそう。
vercelへのデプロイ時にsuspenseの箇所でエラーをthrowしていると落ちてしまうのでRSC側のclient作成時もsuspenseをtrueにしてデプロイすると通るようになりました。

詰まっていたところも割と解決してきたのでこの質問はcloseします。
ありがとうございました。

投稿2023/07/29 16:55

TatsuyaOkawa

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問