next.js - useQuery 是否在服务器端渲染上运行?

标签 next.js apollo apollo-client

我是 Nextjs 的新手,对 Nextjs 中的客户端渲染和服务器端渲染有一些疑问

  • 我看到有两种方法可以在 Nextjs 上获取数据。其中之一是使用 useQuery hook 但只能在 React 组件函数上调用。这是否意味着它仅在从客户端渲染页面时运行
  • 我读了一篇关于如何连接的帖子 apolloClient到 Nextjs。它说

  • always create a new instance of apolloClient for SSR and only create one instance of apolloClient for CSR


    这是示例代码
      export function initializeApollo(initialState = null) {
        const _apolloClient = apolloClient ?? createApolloClient();
    
        // If your page has Next.js data fetching methods that use Apollo Client,
        // the initial state gets hydrated here
        if (initialState) {
          // Get existing cache, loaded during client side data fetching
          const existingCache = _apolloClient.extract();
    
          // Restore the cache using the data passed from
          // getStaticProps/getServerSideProps combined with the existing cached data
          _apolloClient.cache.restore({ ...existingCache, ...initialState });
        }
    
        // For SSG and SSR always create a new Apollo Client
        if (typeof window === "undefined") return _apolloClient;
    
        // Create the Apollo Client once in the client
        if (!apolloClient) apolloClient = _apolloClient;
        return _apolloClient;
      }
    
    
    谁能解释一下?如果问题很愚蠢,我很抱歉

    最佳答案

    在下一个 JS 中:

  • SSR - 服务器端渲染 - getServerSideProps
  • SSG - 生成静态站点 - getStaticPaths/getStaticProps
  • CSR - 客户端渲染 - 其他所有内容

  • 需要注意的是,SSG 是服务器端。
    在客户端 (CSR) 上,您只想创建 Apollo Client 的单个全局实例。创建 Apollo Client 的多个实例将使在客户端上保持同步变得具有挑战性。这个困难是因为 Apollo Cache、Apollo Link 等,都会存储在不同的 Apollo Client 实例中。
    在Next中,通常将Apollo Client的全局实例放置在页面_app.js并使用 Apollo Provider .在其他客户端页面上,您将使用 useQuery调用您的单个全局实例的钩子(Hook)。
    服务器端 (SSR) 函数 getStaticProps 或 getServerSideProps 无权访问 Apollo 的客户端实例、Next 的客户端实例或其他服务器端函数。因此,您必须在每个使用 getStaticPaths、getStaticProps 或 getServerSideProps 并需要访问 Apollo 客户端的页面上定义 Apollo 连接,否则服务器端调用将无法使用它。
    自,第一rule of hooks是它们只能在顶层(客户端)调用,您不能在服务器端函数中使用它们。不,您不能在 Next SSR 或 SSG 函数中运行 useQuery。
    您提供的示例是保持缓存同步并且是 outdated in how it is defining the client .这是一个更符合官方文档的简化示例。
    graphqlClient.js
    import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
    
    // Used server and client side - can't use react hooks
    export const graphqlClient = new ApolloClient({
      cache: new InMemoryCache(),
      link: new HttpLink({
        uri: 'YOUR_GQL_ENDPOINT',
      }),
      ssrMode: typeof window === 'undefined',
    });
    
    _app.js - 所有客户端页面都使用的单个实例,因为它包装了整个应用程序
    import graphqlClient from 'my/path/graphqlClient';
    
    const App = ({ Component, pageProps }) => {
      const client = graphqlClient();
      return (
        <ApolloProvider client={client}>
          <Component {...pageProps} />
        </ApolloProvider>
      );
    };
    
    每个需要访问 Apollo 的客户端页面都使用 useQuery 钩子(Hook)
    客户端
    import { gql, useQuery } from '@apollo/client';
    import graphqlClient from 'my/path/graphqlClient';
    
    const About = () => {
     const { data } = useQuery(YOUR_QUERY); // uses your single instance defined in _app.js
     const { data } = await client.query({query: YOUR_QUERY});
     return (
       ...
     )
    }
    
    每个使用 SSR 或 SSG 功能并需要访问 Apollo 的页面都必须实例化一个新的 Apollo 实例。
    SSG
    import graphqlClient from 'my/path/graphqlClient';
    
    //does not have access to _app.js or client and must define new Apollo Client instance
    export const getStaticProps = async () => {
      const client = graphqlClient();//
      const { data } = await client.query({query: YOUR_QUERY});
    };
    
    export const getStaticPaths = async () => {
      const client = graphqlClient();
      const { data } = await client.query({query: YOUR_QUERY});
    };
    
    固态继电器
    import graphqlClient from 'my/path/graphqlClient';
    
    //does not have access to _app.js or client and must define new Apollo Client instance
    export const getServerSideProps = async () => {
      const client = graphqlClient();
      const { data } = await client.query({query: YOUR_QUERY});
    };
    
    最后,为了简化事情,您可以使用 graphql-code-generator自动生成 Apollo 查询、变异等钩子(Hook)(和 TS 用户的类型)以及服务器端兼容 query and mutation functions for Next.js .

    关于next.js - useQuery 是否在服务器端渲染上运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67163527/

    相关文章:

    reactjs - 我可以同时使用 Gatsby 和 NEXT.JS 吗?

    Azure Cosmos db 和函数 javascript sdk - 如何异步读取文档?

    javascript - Apollo 中的 GraphQL 架构存在问题

    graphql - 为什么使用 Apollo GraphQL Server Express(或其他集成)?

    angular - 当我从 Angular 传递 graphql 查询时,为什么 GraphQL Controller 中的参数查询为空?

    用于 C++ 和 .NET 的 GraphQL 客户端

    javascript - 使用 Next.js 和 Headless Wordpress 作为后端时出现 CORS 问题

    javascript - 我该如何做顶级等待

    next.js - 为什么 nextJS 导出页面中的某些文件如此之大(> 26MB)?

    javascript - Apollo-客户端自签名证书