微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

useQuery 是否在服务器端渲染上运行?

如何解决useQuery 是否在服务器端渲染上运行?

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

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

总是为 SSR 创建一个新的 apolloClient 实例,并且只为 CSR 创建一个 apolloClient 实例

这是示例代码

  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 客户端的单个全局实例。创建 Apollo Client 的多个实例将使在客户端上保持同步变得具有挑战性。这个难点是因为 Apollo Cache、Apollo Link 等,都会存储在不同的 Apollo Client 实例中。

在 Next 中,通常将 Apollo Client 的全局实例放置在页面 _app.js 上并使用 Apollo Provider。在其他客户端页面上,您将使用 useQuery 挂钩来调用您的单个全局实例。

服务器端 (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 钩子

客户端

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});
};

SSR

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});
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。