React Native项目使用react-apollo实现更新缓存的两种方式

栏目: IOS · Android · 发布时间: 5年前

内容简介:举个例子:在显示动态的页面中删除某一条动态之后退出该页,当再进入该页之后这个被删除的动态是否还显示?显示! 为啥?

背景:

举个例子:在显示动态的页面中删除某一条动态之后退出该页,当再进入该页之后这个被删除的动态是否还显示?

显示! 为啥? cache

cache 是为了增强用户体验,如果每一次进入一个页面都需要从网络获取数据,当数据量很大时却迟迟加载不出来,麻爪了吧.....

但是现在 cache 的存在却给我们造成了很大的困扰:

我虽然删除了这条动态,并配合使用 react-nativestate 进行状态变化将这个动态在视觉上被删除掉了,但我没有重新获取数据,更新数据。当我从外界再次进入这个页面之后页面上显示的数据还是从 cache 中获取的数据。因此必须要更新 cache !!

在前面的博客中提到, GraphQL 是一个 API 查询语言,他可以将使用 PostgreSQL 写的 server 代码自动生 成Query 或者 Mutation ,非常的方便。而 Apollo Client 就是一个强大的 JavaScript GraphQL 客户端。对于 cache ,在 Apollo Client 中有着强大的管理策略。

在近阶段的使用过程中,我总结了两种管理缓存的办法:

  1. 手动更新缓存
  2. 自动更新缓存

一:手动更新缓存

在不断的搜索中我在文档中找到了他:

https://www.apollographql.com...

React Native项目使用react-apollo实现更新缓存的两种方式

一个可以自定义访问,或者直接访问apollo缓存的指南

看到这的时候我似乎有些明白了,人家都给你说的很明白了。你管理缓存的方式有两种一种是自定义,另一种是自动。

fuck。武林秘籍都放在这,我却因为看不懂武林秘籍上的字迟迟不能升级????

应用场景:

如图一个消息隐藏的选择开关,当进行选择之后就会自动触发 react-apollomutation 操作,将这种变化传递到数据库,但是如果不更新缓存,当你退出本页面,再进来时就会发现消息隐藏的开关显示和原来还是一样的。因此需要进行缓存的更新。

React Native项目使用react-apollo实现更新缓存的两种方式

第一段代码:GraphQL定义mutation

export const UPDATE_PERSON_SETTING = gql`
mutation updatePersonById($input: UpdatePersonByIdInput!) {
  updatePersonById(input: $input) {
    clientMutationId
    person {
    hideSpeaker
    }
  }
}
`

第二段代码: Mutation组件mutate操作

(请先阅读官网相关部分之后再看)

<Mutation mutation={UPDATE_PERSON_SETTING} variables={{ input: { id: currentPerson.id,
            personPatch: {
              hideSpeaker: true
            } } } }
          update={(cache, { data: { updatePersonById } }) => {
            this.updateCacheAfterSwitchHideSpeak(cache, updatePersonById.person.hideSpeaker)
          }
          }
          >
            {updatePersonById => (
              <Switch value={currentPerson.hideSpeaker} onValueChange={value => {
                updatePersonById({ variables: { input: { id: currentPerson.id,
                  personPatch: {
                    hideSpeaker: value
                  } } } })
              }}
              />
            )}
          </Mutation>

分析:

采用 UPDATE_PERSON_SETTING 这段 GraphQL mutation 操作在对开关进行更改,同时返回了更改后的数据 hideSpeaker

Mutation 这个组件中第三个参数 update 是一个箭头函数,函数的第一个参数是 cache ,第二个参数 data是用来更改缓存的数据 。这个 data 就来自于第一段代码中 mutation 操作的返回值。

在函数体中,调用用于更改缓存的函数 updateCacheAfterSwitchHideSpeak ,一并将 cache和data 传入其中。

接下来分析一下第三段代码

第三段代码:更新缓存函数

updateCacheAfterSwitchHideSpeak = (cache, value) => {
    const data = cache.readQuery({
      query: CURRENT_PERSON
    })
    data.currentPerson.hideSpeaker = value
    cache.writeQuery({ query: CURRENT_PERSON, data })
  }

当接收到 cache和value 之后,输出一下 cache ,发现里面存在两个方法: readQuery,writeQuery ,这两个方法就是我们用来进行读取缓存和更改缓存的办法。

注意:

这里的 query 参数必须要和渲染这个组件时所获取数据的 query 来源是一致的。

也就是说,必须是同一个 GraphQL API 。如果存在 variables ,那么 variables 也必须是一样的。

结合实际情况:在进入这个设置页面时,通过调用一个 GraphQL 查询 API 并且将 hideSpeaker 查询出来,渲染出页面。而查询的结果也就形成了一个缓存。一个项目中有很多的查询,有些页面使用同一个 GraphQL API 进行查询,但是他们的 condition 却不同这就会造成 cache 的不同,因此在查询过程中如果存在 variables ,就必须进行严格的限制,确保从 cachereadQuery 出来的 data 就是你梦寐以求的那个Ta -_-。

下面是一段带有variables的readQuery代码。

const variables = {
       personPostCondition: { personId: personId },
       likeCondition: { personId: personId },
       orderBy: 'CREATED_AT_DESC'
     }
     const data = cache.readQuery({
       variables,
       query: PERSON_DYNAMICS
     })

在读取完 cache 中的 data 之后,你可以输出一下,看是不是当时你在渲染页面时 query 的数据,但是此时消息隐藏已经进行了调整,相应的 hideSpeaker 却还是 false ,此时单独将这个属性拿出来进行调整: data.currentPerson.hideSpeaker = value 在修改完后再使用 writeQuery 将新的 cache 写进去。此时就完成了 cache 的更改。

query和readQuery的区别

query 的数据查询来源有两个:

1:服务器

2:缓存

readQuery 的数据查询来源只有一个:

1:缓存

如果缓存中不存在,他就会报错,因此使用这个方法的前提就是已经使用了 query 将数据从服务器获取到了。

当然据官网上的描述,手动更改缓存的方式还有几种,但是目前还没有仔细的看过。日后再进行解释说明。

二:自动更新缓存

与手动更新相对的自然就是自动更新了。

既然有自动更新功能,他肯定是借助了什么逆天的“工具”!

apollo-cache-inmemory

这一点在官网也已经有了详细的说明了:

React Native项目使用react-apollo实现更新缓存的两种方式

安排的明明白白的了,在 Apollo Client 2.0apollo-cache-inmemory 他是默认实现的。因此,只要使用了 Apollo Client 2.0npm 时他是会进行相应的自动安装的。

缓存的标准化管理是实现自动更新缓存的前提!!!

inmemory 是一个规范化的数据存储,他是咋规范化的呢???

React Native项目使用react-apollo实现更新缓存的两种方式

query 到数据之后, InMemoryCache 对查询来的数据进行分割成单个的对象并保存。

而且为这些单个的对象都设置唯一的标识符,如果在 query 数据时将那些可以作为唯一标识符的字段例如 id 也一并获取到了,那么就将这个 id 作为分割后对象的唯一标识符。

React Native项目使用react-apollo实现更新缓存的两种方式

React Native项目使用react-apollo实现更新缓存的两种方式

上面这个简单的例子说明,如果 id 相同,那么 score在 缓存中的数据也会自动进行更新。

因此结合我们之前的实例做一个简单的更改:

export const UPDATE_PERSON_SETTING = gql`
mutation updatePersonById($input: UpdatePersonByIdInput!) {
  updatePersonById(input: $input) {
    clientMutationId
    person {
    id
    hideSpeaker
    }
  }
}
`

我们在进行 mutation 之后的返回值中存在 id ,这就符合上面的要求。他就会自动进行缓存的更新。

如果你还心存疑虑,你大可在 readQuery 后将 data 输出一下,此时你就会发现 hideSpeaker 已经更改成目前的状态 true 。这就是自动更新的快捷之处。此时你就不必使用 readQuery和writeQuery 这种费时费力的方法了。

三:最后的话

1:不论是自动更新还是手动更新,都必须将更改之后的数据返回出来,就像 hideSpeaker ,更改他之后,你必须将它返回出来。这不论是在自动更新还是在手动更新上都是有必要的。

2:关于两者的选择使用,毫无疑问,通常情况下使用自动更新,特殊情况下使用手动更新,在明白原理后,有时你可以使用手动更新进行一些投机取巧的更新缓存的操作。

3:难,都难。爬,一起爬。


以上所述就是小编给大家介绍的《React Native项目使用react-apollo实现更新缓存的两种方式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员修炼之道

程序员修炼之道

[美]享特 / 人民邮电出版社 / 2007-12 / 49.00元

《程序员修炼之道》适合各层次软件开发人员阅读,也适合高等院校计算机专业学生和教师阅读。一起来看看 《程序员修炼之道》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具