next.js React Query SSR预取查询未触发请求

cgh8pdjw  于 2023-06-22  发布在  React
关注(0)|答案(1)|浏览(158)

我正在尝试从SpaceX的GraphQL API获取一些数据。我正在使用Next,React Query和GraphQL代码生成器。
一旦生成了所有内容,使用queryClient.prefetchQuery的SSR实现就不能像我期望的那样工作,因为HTML文档总是空白的。边注通过使用不使用代码生成预取工作如预期。
这是我的简化工作示例:

index.tsx

..
import { useQuery, QueryClient, dehydrate } from "react-query"
import { gql, request } from 'graphql-request'

const API_URL = "https://api.spacex.land/graphql/";

const getLaunchesPast = async () => {
  const data = await request(
    API_URL, 
    gql`...query...`
  );
  return data;
};

const Home: NextPage = (props) => {
  const { data } = useQuery("launchesPast", getLaunchesPast);
  return (...);
}

export const getServerSideProps = async () => {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery('launchesPast', getLaunchesPast);
  
  return {
    props: {
      dehydratedState: dehydrate(queryClient)
    }
  }
}
export default Home

使用这种方法,我能够看到HTML文档最初呈现的数据。然而,当尝试使用代码生成并连接起来时,我不再能够预取服务器端而只能获取客户端

launchesPast.gql

query getLaunchesPast($limit: Int) {
    launchesPast(limit: $limit) {
      mission_name
      launch_date_local
    }
  }
condegen.yml

overwrite: true
schema: "https://api.spacex.land/graphql/"
documents: "./src/graphql/**/*.gql"
generates:
  src/generated.ts:
    plugins:
      - typescript
      - typescript-operations
      - typescript-react-query
    config:
      pureMagicComment: true
      exposeQueryKeys: true
      fetcher: graphql-request
        endpoint: "https://api.spacex.land/graphql/"
        fetchParams:
          headers:
            Content-Type: "application/json"
      exposeFetcher: true
_app.tsx

import { useState } from 'react'
import type { AppProps } from 'next/app'
import { Hydrate, QueryClient, QueryClientProvider } from 'react-query'
import { ReactQueryDevtools } from 'react-query/devtools'

function MyApp({ Component, pageProps }: AppProps) {
  const [queryClient] = useState(() => new QueryClient());

  return (
    <QueryClientProvider client={queryClient}>
      <ReactQueryDevtools initialIsOpen={false} />
      <Hydrate state={pageProps.dehydratedState}>
        <Component {...pageProps} />
      </Hydrate>
    </QueryClientProvider>
  );
}

export default MyApp
index.tsx

import type { NextPage } from 'next'
import Head from 'next/head'
import { QueryClient, dehydrate} from "react-query"[![enter image description here][1]][1]

import { GetLaunchesPastQuery, useGetLaunchesPastQuery } from '../generated';

const Home: NextPage = (props) => {
  const { data, isFetching } = useGetLaunchesPastQuery<GetLaunchesPastQuery>({ limit: 5 });

  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        {data?.launchesPast && (
          <ul>
            {data?.launchesPast.map((launch) => (
              <li key={launch?.mission_name}>{launch?.mission_name} ({launch?.launch_date_local})</li>
            ))}
          </ul>
        )}
      </main>
    </div>
  );
}

export const getServerSideProps = async () => {
  const queryClient = new QueryClient();

  await queryClient.prefetchQuery(useGetLaunchesPastQuery.getKey(), () =>
    useGetLaunchesPastQuery.fetcher({ limit: 10 })
  );

  return {
    props: {
      dehydratedState: JSON.parse(JSON.stringify(dehydrate(queryClient))),
    },
  };
};

export default Home

rqqzpn5f

rqqzpn5f1#

我遇到了同样的问题,没有太多关于用法的信息,当你使用infiniteQuery时,你需要在服务器中使用prefetchInfiniteQuery而不是prefetchQuery
示例:

export const getServerSideProps: GetServerSideProps = async ({
  query,
  req,
}) => {

  const queryClient = new QueryClient();

  const result = await queryClient.prefetchInfiniteQuery(
    {
      queryKey: useInfiniteGetProductsStoreFrontQuery.getKey({ limit: 3 }),
        // Take care use the method without the prefix Infinite and then in the client side the keys need to match 
      queryFn: useGetProductsStoreFrontQuery.fetcher(client, {
        limit: 3,
      }),
    }

return {
    props: {
      dehydratedState: JSON.parse(JSON.stringify(dehydrate(queryClient))),
     },
  };

客户端

const { data, fetchNextPage } = useInfiniteGetProductsStoreFrontQuery(
    "page",
    client,
    {
      limit: 3
    },
    {
      getNextPageParam: (lastPage, pages) => {

        if (lastPage.searchProductsStoreFront.length > 0) {
          return {
            page: pages.length + 1,
          };
        }
      }
    }
  );

在这个示例中,您将拥有已经缓存的数据

相关问题