- 前端
【免费下载链接】react-apollo
:recycle: React integration for Apollo Client
本指南以 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 Apollo
Query,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-components | Query、Mutation、Subscription |
| Hooks | @apollo/react-hooks | useQuery、useLazyQuery、useMutation、useSubscription、useApolloClient |
| 高阶组件 | @apollo/react-hoc | graphqlHOC |
值得强调的是,三个 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
相关推荐
React Apollo组件化开发:Query、Mutation、Subscription最佳实践
React Apollo组件化开发:Query、Mutation、Subscription最佳实践 React Apollo作为Apollo Client的Re
前端Apollo Client MockedProvider 深度指南:基于 @apollo/client/testing/react 构建可靠的 React 组件测试
Apollo Client MockedProvider 深度指南:基于 @apollo/client/testing/react 构建可靠的 React 组件
前端GraphQLLearn Apollo React 教程(6/7):使用 Apollo Client 在单个组件中组合多个 Mutation 实现宝可梦更新与删除
Learn Apollo React 教程(6/7):使用 Apollo Client 在单个组件中组合多个 Mutation 实现宝可梦更新与删除 导读 本练
教程前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考