実現したいこと
-
Next.js
とgraphql
、urql
を使用したシンプルコードをvercel
にデプロイしてエラーなく動かしたい -
urql
のsuspense
を用いて ロード中の描画を行いたい
前提
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.ts
にapollo-server
を用いて実装しています。 - 特にサーバーの実装はしていないのでmockとして定数を返しています。
その他必要な情報があればコメント追記しますのでコメントいただければと思います。
何卒、よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。