如何在单个项目中使用多个版本的 Apollo 客户端

Posted

技术标签:

【中文标题】如何在单个项目中使用多个版本的 Apollo 客户端【英文标题】:how to use multiple versions of Apollo client in single project 【发布时间】:2021-02-17 05:31:45 【问题描述】:

我正在接管一个较旧的 React/Apollo/GraphQL 项目,这些项目目前没有使用 useQuery、useMutation 等钩子。所以我正在尝试进行升级。

我已经安装了 @apollo/react-hooks 包,并在我的 App.js 中替换了 ApolloProvider

//import  ApolloProvider  from 'react-apollo'; //Old
import  ApolloProvider  from '@apollo/react-hooks'; //New

<ApolloProvider client=apolloClient>......</ApolloProvider>

但是,这会在运行应用程序时导致错误:

index.mjs?8baf:1 Uncaught ReferenceError: module is not defined 在 eval (index.mjs?8baf:1) 在 Module../node_modules/graphql/index.mjs (vendors.aa829d69df1a68216354.js:7568) 在 webpack_require (app.aa829d69df1a68216354.js:780) 在 fn (app.aa829d69df1a68216354.js:148) 在 eval (index.js:3) 在 Object../node_modules/@apollo/client/utilities/index.js

我的 package.json 有以下相关的包:

"react-apollo": "^2.0.1",
"react": "^16.14.0",
"apollo-cache-inmemory": "^1.1.12",
"apollo-client": "^2.6.10",
"@apollo/react-hooks": "^4.0.0",
"apollo-link": "^1.2.2",
"apollo-link-batch-http": "^1.2.2",
"apollo-link-context": "^1.0.8",
"apollo-link-error": "^1.0.9",
"apollo-link-http": "^1.5.4",
"apollo-link-ws": "^1.0.8",
"apollo-utilities": "^1.0.11"

如果我尝试使用“react-apollo”中的 ApolloProvider,我可以运行我的应用程序,但添加时:

import useQuery from '@apollo/react-hooks';

应用程序无法加载。

我希望有人在有解决方案之前遇到过同样的情况。在此先感谢

【问题讨论】:

【参考方案1】:

也许您需要再次阅读 Apollo 文档。

这是Introduction to Apollo Client for React的链接。

取自Apollo Docs for React:

import React from 'react';
import  render  from 'react-dom';

import  ApolloProvider  from '@apollo/client';

function App() 
  return (
    <ApolloProvider client=client>
      <div>
        <h2>My first Apollo app ?</h2>
      </div>
    </ApolloProvider>
  );


render(<App />, document.getElementById('root'));

您需要从@apollo/client 导入ApolloProvider,而不是从@apollo/react-hooks

并尝试安装与 apollo react 相关的所有内容的第 4 版。否则,你可能会遇到很多像我一样的错误here


编辑:

如果您想在逐步重构代码时合并两个版本,请尝试将使用 Apollo v4 创建的 client 直接提供给 hooks。这是我们目前在工作中使用的方法。

useQueryuseMutation 具有 options 对象,可以采用 client 实例。因此,尝试使用新的 Apollo v4 包创建一个新的client 实例,而不是将这个新的client 传递给ApolloProvider,而是在每个组件中导入客户端并使用options 显式地将其提供给挂钩目的。完成对钩子的重构后,您可以将组件包装在ApolloProvider 中并删除options 对象中的client 实例(即使您不删除它,它也可以正常工作,直到您继续使用相同的@ ApolloProvideruseQueryuseMutationoptions 对象中的 987654341@(Apollo v4) 实例。


编辑:2

问题是您当前使用的是 Apollo Client v2.6。但较新的版本是 Apollo Client v3.x。而新版@apollo/react-hooks显然期待你使用最新的Apollo Client v3.x。

因此,您需要维护两个 apollo 客户端文件,直到您重构整个代码库以响应钩子。

    使用 apollo-client^2 - 与您现有的代码(您已经拥有)一起使用 使用 @apollo/client^3 - 与 apollo 挂钩使用

当你这样做时,

<ApolloProvider client=oldClientCreatedUsingv2>
      <div>
        <h2>My first Apollo app ?</h2>
      </div>
</ApolloProvider>

useQueryuseMutation 挂钩使用ApolloProvider 中提供的client。但是你显然不能将它用于两个ApolloProviders 版本。这将是冲突的。

所以,在ApolloProvider 中提供您的 v2 apollo 客户端实例,这样您现有的代码库就不会受到干扰。 实际上,您甚至不必在此处修改任何内容。就让它成为现在的样子吧。

并在useQueryuseMutation 中,提供v3 apollo 客户端实例(即,使用@apollo/client 创建客户端,如this)。 这是您唯一需要做的事情。

接下来,在使用钩子进行查询或突变时,在任何地方提供使用 v3 创建的客户端:

const loading, error, data  = useQuery(YOUR_QUERY,  client: newClientCreatedUsingv3 );

ApolloProvider 仅用于传递client,这样我们就不必在每个组件中都导入它并将其传递给useQueryuseMutation 或HOC 的钩子。

如果您在发出请求时明确提供客户端,则它不会使用ApolloProvider 中提供的客户端。

一旦您将代码完全重构为使用 React 钩子,您就可以像这样更改 ApolloProvider

<ApolloProvider client=newClientCreatedUsingv3>
      <div>
        <h2>My first Apollo app ?</h2>
      </div>
</ApolloProvider>

现在,您可以从每个useQueryuseMutation 中删除client 选项以进一步清理代码,因为从现在开始useQueryuseMuation 将开始使用newClientCreatedUsingv3 中提供的实例ApolloProvider.

希望这可以澄清。

【讨论】:

但这是否适用于向后兼容?原因是我不能一次更改所有查询和突变,但随着时间的推移会这样做,所以我仍然需要支持 compose 和 graphql HOC @envy 我已经编辑了我的答案,以获取关于我们如何在工作中使用新旧 apollo 包的建议。它应该可以帮助你 感谢答案:) 虽然我不确定你的意思是当你说“尝试将使用 Apollo v4 创建的客户端直接提供给钩子”时?正如我所听到的,你想要两个不同的阿波罗客户?您是否有这方面的示例,以及它是如何在基于类和函数的组件中使用的? @envy 我已经用更详细的解释编辑了我的答案。我希望它能澄清你的问题。 @envy 也许您需要将您的问题修改为“如何在单个项目中使用多个版本的 Apollo 客户端”,以便其他人将来可以从您的用例中受益

以上是关于如何在单个项目中使用多个版本的 Apollo 客户端的主要内容,如果未能解决你的问题,请参考以下文章

在 apollo graphql 的单个 useEffect 挂钩中使用多个查询

Apollo 客户端:如何对自定义事件执行查询

在客户端解析器中导入类型时,如何避免使用 Apollo 客户端和“graphql-codegen”的角度项目中的循环依赖?

如何在 Apollo Client React 中获取多个条件查询?

如何使用动态别名在单个请求中多次调用 GraphQL 突变

如何在 GraphQL Apollo 客户端中处理异步突变