GraphQL 入门: Apollo Client 存储API

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)合并html

Apollo Client 使用四个方法来控制存储:readQuery, readFragment, writeQuery, writeFragment. Apollo Client 的这些实例方法可让你直接读写缓存. react

用这四个方法可以让你自定义Apollo Client的行为. 下面咱们介绍每一个方法的细节.segmentfault

从存储读取查询

第一个和存储交互的方法是readQuery. 该方法用于从根查询开始读取缓存数据, 下面是读取数据的例子:后端

const data = client.readQuery({
  query: gql`
  {
    todo(id: 1) {
      id
      text
      completed
    }
        
  }
  `
});

若是数据在缓存中已经存储, 它将会直接返回并存储到组件的data属性, 而不须要向服务器请求, 若是在缓存中找不到查询对应的数据, 将会抛出一个错误.api

你能够在应用中任何地方使用一个查询, 还能够传入变量:浏览器

import { TodoQuery } form './TodoGraphQL';

const data = client.readQuery({
  query: TodoQuery,
  variables: {
    id: 5
  }
});

readQueryquery 相似, 可是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() 方法. 这两个方法让你可以更新缓存中的数据, 用于模拟来自服务器的数据更新. 可是注意这些数据没有持久化到后端, 若是你刷新你的浏览器, 这些更新的数据将会丢失.

用户不会注意到有什么区别, 若是更新数据要对全部用户可见, 须要把更新的数据持久化到后端服务器.

writeQuerywriteFragment 的优势是, 它们让你可以修改缓存中的数据以确保数据可以同步到服务器, 而且在执行一次服务器彻底刷新的时候不会丢失你的数据更新. 这让你可以部分的修改客户端数据, 给用户提供更好的体验.

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 函数不一样的是, 他会覆盖全部重叠的数据节点

参考资料

相关文章
相关标签/搜索