GraphQL 入门: 简介
GraphQL 入门: Apollo Client - 简介
GraphQL 入门: Apollo Client - 安装和配置选项
GraphQL 入门: Apollo Client - 连接到数据
GraphQL 入门: Apollo Client - 网络层
GraphQL 入门: Apollo Client - 开发调试工具
GraphQL 入门: Apollo Client - 持久化GraphQL查询概要
GraphQL 入门: Apollo Client - 存储API
GraphQL 入门: Apollo Client - 查询(Batching)合并
Apollo Client
使用四个方法来控制存储:readQuery
,readFragment
,writeQuery
,writeFragment
. Apollo Client 的这些实例方法可以让你直接读写缓存.
用这四个方法能够让你自定义Apollo Client的行为. 下面我们介绍每个方法的细节.
从存储读取查询
第一个和存储交互的方法是readQuery
. 该方法用于从根查询开始读取缓存数据,下面是读取数据的例子:
const data = client.readQuery({ query: gql` { todo(id: 1) { id text completed } } ` });
如果数据在缓存中已经存储,它将会直接返回并存储到组件的data
属性,而不需要向服务器请求,如果在缓存中找不到查询对应的数据,将会抛出一个错误.
你可以在应用中任何地方使用一个查询,还可以传入变量:
import { TodoQuery } form './TodoGraphQL'; const data = client.readQuery({ query: TodoQuery,variables: { id: 5 } });
readQuery
和 query
类似,但是readQuery
不会发送请求到服务器,它总是期望从缓存中查询数据,如果缓存中找不到对应的数据,将会抛出一个错误.
从存储读取片段
有时候你希望重缓存中读取任意的数据,而不仅仅是根查询类型. 对此有一个 readFragment()
方法用于这类用途. 该方法接受 GraphQL 片段和一个 ID,并返回 ID 对应的数据片段.
client.readFragment({ id: '5',fragment: gql` fragment todo on Todo { id text completed } ` });
id
应该是一个由 dataIdFromObject
函数返回的字符串,这个字符串是在 Apollo Client 初始化的时候通过 dataIdFromObject
函数进行定义.
const client = new ApolloClient({ dataIdFromObject: o => { if(o.__typename != null && o.id != null) { return `${o.__typename}-${o.id}`; } } });
因为在id
前面添加了变量__typename
,然后id
的值变为Todo5
.
向存储写入查询和片段
和读取查询和片段对应的还有 writeQuery()
和 writeFragment()
方法. 这两个方法让你能够更新缓存中的数据,用于模拟来自服务器的数据更新. 但是注意这些数据没有持久化到后端,如果你刷新你的浏览器,这些更新的数据将会丢失.
用户不会注意到有什么区别,如果更新数据要对所有用户可见,需要把更新的数据持久化到后端服务器.
writeQuery
和 writeFragment
的优点是,它们让你能够修改缓存中的数据以确保数据能够同步到服务器,并且在执行一次服务器完全刷新的时候不会丢失你的数据更新. 这让你能够部分的修改客户端数据,给用户提供更好的体验.
writeQuery()
和 readQuery
有相同的接口,和 readQuery
不同的是 writeQuery
还有一个 data
参数. data
对象的结构必须和服务器返回的JSON结果的结构相同.
client.writeQuery({ query: gql` { todo(id: 1) { completed } } `,data: { todo: { completed: true },},});
同样的,writeFragment()
和 readFragment()
也有相同的接口,并且多一个 data
参数. id
遵循和 readFragment()
相同的规则:
client.writeFragment({ id: '5',fragment: gql` fragment todo in Todo { completed } `,data: { completed: true } });
这四个方法让你能够完全的控制缓存中的数据.
使用读和写来更新数据
因为从缓存中获取的数据只是一份拷贝,不影响底层的存储.
const query = gql` { todos { id text completed } } `; const data = client.readQuery({ query }); data.todos.push({ id: 5,text: 'Hello,world!',completed: false }); client.writeQuery({ query,data });
在一个Mutation之后执行更新
const text = 'Hello,world!'; client.mutate({ // GraphQL Mutation 更新语句 mutation: gql` mutation ($text: String!) { createTodo(text: $text) { id text completed } } `,// 变量 variables: { text,optimisticResponse: { createTodo: { id: -1,// Fake id text,completed: false,// 更新函数 // 用Mutation返回的结果对存储进行更新,并触发React UI组件的重新渲染 update: (proxy,mutationResult) => { const query = gql` { todos { id text completed } } `; // 从缓存中读取数据 const data = proxy.readQuery({ query,}); // 用Mutation的结果更新数据 data.todos.push(mutationResult.createTodo); // 写回缓存 proxy.writeQuery({ query,data,}); },});
update
函数有两个参数:
proxy
是一个 DataProxy 对象,主要用于与底层存储进行数据交互mutationResult
是一个Mutation操作的响应,可以是一个乐观应答,或服务器实际的应答.
updateQueries
也可以使用updateQueries
回调函数对数据进行更新. 详细的API接口可参考 updateQueries
updateQueries
也是基于 Mutation 的返回结果对存储进行更新,和 update
函数不同的是,他会覆盖所有重叠的数据节点