☰
@apollo/react-components 完全指南:深入理解 React Apollo 的 Query、Mutation 与 Subscription 组件
2026/10/15 19:02:36 网站建设 项目流程
  • 前端

【免费下载链接】react-apollo

:recycle: React integration for Apollo Client

项目地址:https://gitcode.com/gh_mirrors/re/react-apollo
点击查看免费下载

本指南以 react-apollo 仓库中 packages/components/README.md 为骨架,系统讲解@apollo/react-components包提供的三个核心渲染属性组件(Render Prop Components)——Query、Mutation与Subscription。你将掌握它们的安装方式、组件职责边界、关键 props 行为,以及 React Apollo 4.0.0 终止发布后如何无缝迁移到@apollo/client3.x 的官方替代入口。

一、包概览:这是什么样的一个包

@apollo/react-components是 React Apollo 官方拆分的五个子包之一(其余为@apollo/react-hooks、@apollo/react-hoc、@apollo/react-ssr、@apollo/react-testing),它面向的是一套经典但依然重要的 React 数据绑定范式:渲染属性组件。按 packages/components/README.md 的原话,这个包提供的是:

React ApolloQuery,MutationandSubscriptioncomponents.

即三个分别对应 GraphQL 三种操作类型的组件:

  • <Query>:执行查询(query),并把查询结果(data、loading、error等)作为渲染函数的参数暴露给子级;
  • <Mutation>:执行变更(mutation),将触发变更的函数与变更结果暴露给子级;
  • <Subscription>:订阅服务端推送(subscription),持续接收实时数据并驱动 UI 更新。

在 React Apollo 3.x 时期,这一组件范式与 Hooks 范式、HOC 范式并存;而到了 Changelog.md 所记载的 3.0.0 版本,这三个组件被内部重构为函数组件,直接包装useQuery、useMutation、useSubscription三个 Hook 的等价实现,因此三者共享同一套数据获取逻辑,只是对外暴露的 API 形态不同。

从本仓库的构建产物可以确认该包的轻量本质:index.js 与 index.esm.js 的全部内容只是对@apollo/client及其子路径@apollo/client/react/components的再导出(re-export),index.d.ts 同样如此。也就是说,这个包本身不再包含独立的实现代码,而是作为旧版 API 的兼容入口存在,这一点对后面的迁移判断非常关键。

二、安装

按 packages/components/README.md 的说明,安装命令为:

npm install @apollo/react-components

从 packages/components/package.json 可以看到该包的工程事实:

  • 版本号4.0.0(React Apollo 系列的最后版本);
  • 唯一运行时依赖为@apollo/client: "latest",印证了"组件实现来自 Apollo Client 3.x"的结构;
  • main指向 CJS 构建index.js,module指向 ESM 构建index.esm.js,types指向index.d.ts,同时声明"sideEffects": false,意味着打包工具可以安全地对其进行 Tree Shaking。

需要特别说明的是:React Apollo 4.0.0 依赖@apollo/client>= 3。如果你仍在apollo-client2.x 且暂不升级,应当使用 React Apollo 3.x(见 Changelog.md 的 Breaking Changes 说明)。

三、<Query>组件:声明式拉取数据

<Query>是三个组件中使用频率最高、也最核心的一个。它通过 render props 把查询生命周期内的所有状态交给调用方渲染,代码形态如下(该模式在 Changelog.md 3.0.0 章节有同构示例):

import { Query } from '@apollo/react-components'; import gql from 'graphql-tag'; const GET_DOG = gql` query GetDog($breed: String!) { dog(breed: $breed) { id name } } `; const Dog = ({ breed }) => ( <Query query={GET_DOG} variables={{ breed }}> {({ loading, error, data, refetch }) => { if (loading) return <p>加载中…</p>; if (error) return <p>出错了:{error.message}</p>; return ( <> <p>{data.dog.name}</p> <button onClick={() => refetch()}>重新拉取</button> </> ); }} </Query> );

渲染函数收到的结果对象包含loading、error、data、refetch、fetchMore等字段,其具体集合以 Apollo Client 的QueryResult为准。

3.1 关键 props 与行为(来自本仓库 Changelog 的可靠记录)

以下特性均有 Changelog.md 的版本记录作为依据,属于该组件的真实能力:

  • skip:设为true时跳过该查询的执行;同时按 2.2.0 的修复记录,跳过状态下渲染函数收到的loading会被置为false,因为此时并没有真正的加载行为。
  • onCompleted/onError:在 2.1.9 中加入,用于注册查询成功或失败后的回调;后续 2.2.0 调整了触发时机,确保数据无论是来自网络还是来自本地缓存都能触发。
  • partialRefetch(默认false,2.2.0 引入):当组件挂载后执行了一个返回相同 ID 但字段更少的 mutation,导致缓存无法命中时,查询数据会被置空。开启该 prop 后,<Query>会自动refetch原查询并更新缓存,避免 UI 因字段被剥离而崩溃。
  • returnPartialData(2.5.6 引入):当缓存里只有查询结果的"子集"(例如另一个组件先缓存了member { id name },本组件要查member { id name plans })时,Apollo 默认会因为无法完整命中而走全量网络请求。开启returnPartialData后,组件会先用缓存中的部分字段渲染(展示局部数据),同时在后台把完整查询拉回来,大幅改善用户体验。
  • notifyOnNetworkStatusChange:为true时,每次网络状态变化(如 refetch 期间)都会触发重新渲染,便于展示"正在刷新"的 UI;3.1.0 还修复了它与fetchMore.updateQuery组合时的多余重渲染问题。

3.2 与 Hooks 的对应关系

在 3.0.0 的重构中,<Query>从可继承的 class 组件改为函数组件并包装useQuery。因此 Changelog.md 明确提醒:不能再通过继承<Query>来扩展它(class SomeQuery extends Query<...>已不可用),替代做法是直接组合使用,或转用 packages/hooks/README.md 中的useQuery。对于希望保留类型安全调用方式的开发者,可以用泛型写法:<Query<SomeData, SomeVariables> query={...}>。

四、<Mutation>组件:声明式触发变更

与<Query>不同,<Mutation>的渲染函数第一个参数是一个触发函数(通常命名为mutate),调用它才真正向服务端发送变更请求:

import { Mutation } from '@apollo/react-components'; import gql from 'graphql-tag'; const ADD_DOG = gql` mutation AddDog($name: String!) { addDog(name: $name) { id name } } `; const AddDogButton = () => ( <Mutation mutation={ADD_DOG}> {(addDog, { data, loading, error }) => ( <button disabled={loading} onClick={() => addDog({ variables: { name: 'Cara' } })} > {loading ? '提交中…' : '添加狗狗'} </button> )} </Mutation> );

4.1 关键 props 与行为(来自本仓库 Changelog 的可靠记录)

  • awaitRefetchQueries(2.1.11 加入,默认false):为true时,refetchQueries中指定的查询会在 mutation 完成之前先全部执行完毕,保证 mutation 的 Promise resolve 时相关查询已刷新;默认情况下 refetch 的查询通常在 mutation 之后完成。
  • refetchQueries按名称触发时的变量问题:2.2.3 修复了"通过字符串名称触发refetchQueries时未使用正确变量"的缺陷。
  • calledprop(2.1.0-rc.4 加入):表示该 mutation 是否已被调用过,可用于区分"尚未调用"与"调用后"的 UI 状态。
  • 错误与结果:2.2.3 修复了默认errorPolicy: 'all'下 mutation 错误未通过 render props 正常返回的问题;2.1.6 起,ApolloClient实例既可以通过clientprop 传入以覆盖 context 中的实例,也会出现在 mutation 的结果对象中。
  • update回调:用于在 mutation 返回后手动把结果写入缓存(与partialRefetch场景互补,是 Changelog.md 推荐的缓存协调方式)。
  • onCompleted/onError:注册变更成功或失败的回调;2.4.0 起,即使<Mutation>组件已卸载,这两个回调仍会被调用。

五、<Subscription>组件:订阅实时数据

<Subscription>用于 WebSocket 等实时推送场景。与查询不同,它会在组件挂载后维持一条长期订阅,每次服务端推送都会触发一次渲染:

import { Subscription } from '@apollo/react-components'; import gql from 'graphql-tag'; const NEW_DOG = gql` subscription NewDog { newDog { id name } } `; const LatestDog = () => ( <Subscription subscription={NEW_DOG}> {({ data, loading }) => { if (loading) return <p>等待推送…</p>; return <p>最新狗狗:{data.newDog.name}</p>; }} </Subscription> );

5.1 关键 props 与行为(来自本仓库 Changelog 的可靠记录)

  • fetchPolicy:2.2.4 起<Subscription>支持fetchPolicyprop,允许调整订阅结果与缓存的交互策略。
  • onSubscriptionComplete:2.4.1 加入,当订阅的 observable 完成(结束)时触发回调,适合做清理或通知。
  • shouldResubscribe:2.1.3 起支持传入函数来决定是否重新订阅,同时修复了组件过度重复订阅的问题;同一版本还修复了订阅结束后无法 refetch 的缺陷。
  • 与skip的配合:3.1.0 为useSubscription加入了skip选项支持,由于组件内部包装了该 Hook,组件层同样受益。

5.2 稳定性相关修复

2.5.7 中修复了<Subscription>在组件已卸载后仍可能设置 state 的问题,规避了 React 的卸载后警告。这说明在长连接场景下,组件的挂载/卸载边界管理是订阅类组件实现的重点。

六、组件、Hooks 与 HOC:三种范式的选型背景

在 React Apollo 3.0.0 的 monorepo 重构中(详见 Changelog.md),官方同时提供三种 React 数据绑定范式:

范式包核心 API
渲染属性组件@apollo/react-componentsQuery、Mutation、Subscription
Hooks@apollo/react-hooksuseQuery、useLazyQuery、useMutation、useSubscription、useApolloClient
高阶组件@apollo/react-hocgraphqlHOC

值得强调的是,三个 render prop 组件在 3.0.0 中已全部改为函数组件并直接包装各自的 Hook 等价物(见 Changelog.md 3.0.0 章节),因此Query/useQuery、Mutation/useMutation、Subscription/useSubscription在数据获取逻辑上完全同源。官方文档在后续版本中已全面转向"hooks-first",但从本指南可以看出,如果你维护的是旧版代码或偏好 render props 的写法,@apollo/react-components依然可用。

七、4.0.0 弃用状态与迁移指南(重要)

这是使用本包前必须知晓的关键事实。根目录 README.md 与 Changelog.md 4.0.0 章节均明确声明:

⚠️THIS PROJECT HAS BEEN DEPRECATED⚠️ 4.0.0 是 React Apollo 所有包的最后版本,React Apollo 的功能已直接并入@apollo/client>= 3。

官方给出的迁移映射为:

旧: @apollo/react-components --> 新: @apollo/client/react/components

也就是说,把导入语句从:

import { Query, Mutation, Subscription } from '@apollo/react-components';

改为:

import { Query, Mutation, Subscription } from '@apollo/client/react/components';

即可获得完全等价的组件能力。之所以迁移如此平滑,正是源于本仓库 index.js 与 index.d.ts 中"纯再导出"的包结构——旧包只是新入口的兼容别名。另外两个迁移注意事项(同样来自 Changelog.md 4.0.0):

  • 4.0.0 起不再构建 UMD 版本;
  • 如果仍在apollo-client2.x 且暂不升级,请继续使用 React Apollo 3.x。

八、仓库佐证:这个包的真实结构

最后,把本包在仓库中的实现证据汇总如下,便于读者自行验证:

  • packages/components/README.md:包说明文档(本文骨架来源),定义了三组件定位与安装方式;
  • packages/components/package.json:@apollo/react-components4.0.0 的工程元数据,依赖@apollo/client,声明sideEffects: false;
  • packages/components/index.js:CJS 入口,逐条展开@apollo/client与@apollo/client/react/components的导出;
  • packages/components/index.esm.js:ESM 入口,内容同上,供打包器进行 Tree Shaking;
  • packages/components/index.d.ts:TypeScript 类型入口,同样来自@apollo/client;
  • Changelog.md:本文所有组件 props 特性(skip、partialRefetch、returnPartialData、awaitRefetchQueries、fetchPolicy、onSubscriptionComplete等)的版本出处。

总结

@apollo/react-components以极简的包结构承载了 React Apollo 经典的三个渲染属性组件:Query负责声明式取数、Mutation负责声明式变更、Subscription负责实时订阅。尽管 4.0.0 已是最终版本,组件本身并未消失——它们以@apollo/client/react/components的形式在 Apollo Client 3.x 中继续演进。理解这三个组件,既是维护旧代码的基础,也是理解 Apollo 数据获取模型从 render props 到 Hooks 演进脉络的关键一环。

  • 前端

【免费下载链接】react-apollo

:recycle: React integration for Apollo Client

项目地址:https://gitcode.com/gh_mirrors/re/react-apollo
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询