React Native项目使用react-apollo实现更新缓存的两种方式
背景:
举个例子:在显示动态的页面中删除某一条动态之后退出该页,当再进入该页之后这个被删除的动态是否还显示?
显示! 为啥? cache
!
cache
是为了增强用户体验,如果每一次进入一个页面都需要从网络获取数据,当数据量很大时却迟迟加载不出来,麻爪了吧.....
但是现在cache
的存在却给我们造成了很大的困扰:
我虽然删除了这条动态,并配合使用react-native
的state
进行状态变化将这个动态在视觉上被删除掉了,但我没有重新获取数据,更新数据。当我从外界再次进入这个页面之后页面上显示的数据还是从cache
中获取的数据。因此必须要更新cache
!!
在前面的博客中提到,GraphQL
是一个API
查询语言,他可以将使用PostgreSQL
写的server
代码自动生成Query
或者Mutation
,非常的方便。而Apollo Client
就是一个强大的JavaScript GraphQL
客户端。对于cache
,在Apollo Client
中有着强大的管理策略。
在近阶段的使用过程中,我总结了两种管理缓存的办法:
- 手动更新缓存
- 自动更新缓存
一:手动更新缓存
在不断的搜索中我在文档中找到了他:
https://www.apollographql.com...
一个可以自定义访问,或者直接访问apollo缓存的指南
看到这的时候我似乎有些明白了,人家都给你说的很明白了。你管理缓存的方式有两种一种是自定义,另一种是自动。
fuck。武林秘籍都放在这,我却因为看不懂武林秘籍上的字迟迟不能升级????
应用场景:
如图一个消息隐藏的选择开关,当进行选择之后就会自动触发react-apollo
的mutation
操作,将这种变化传递到数据库,但是如果不更新缓存,当你退出本页面,再进来时就会发现消息隐藏的开关显示和原来还是一样的。因此需要进行缓存的更新。
第一段代码:GraphQL定义mutation
export const UPDATE_PERSON_SETTING = gql`
mutation updatePersonById($input: UpdatePersonByIdInput!) {updatePersonById(input: $input) {clientMutationIdperson {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 = valuecache.writeQuery({ query: CURRENT_PERSON, data })}
当接收到cache和value
之后,输出一下cache
,发现里面存在两个方法:readQuery,writeQuery
,这两个方法就是我们用来进行读取缓存和更改缓存的办法。
注意:
这里的query
参数必须要和渲染这个组件时所获取数据的query
来源是一致的。
也就是说,必须是同一个GraphQL API
。如果存在variables
,那么variables
也必须是一样的。
结合实际情况:在进入这个设置页面时,通过调用一个GraphQL
查询API
并且将hideSpeaker
查询出来,渲染出页面。而查询的结果也就形成了一个缓存。一个项目中有很多的查询,有些页面使用同一个GraphQL API
进行查询,但是他们的condition
却不同这就会造成cache
的不同,因此在查询过程中如果存在variables
,就必须进行严格的限制,确保从cache
中readQuery
出来的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
这一点在官网也已经有了详细的说明了:
安排的明明白白的了,在Apollo Client 2.0
中apollo-cache-inmemory
他是默认实现的。因此,只要使用了Apollo Client 2.0
在npm
时他是会进行相应的自动安装的。
缓存的标准化管理是实现自动更新缓存的前提!!!
inmemory
是一个规范化的数据存储,他是咋规范化的呢???
在query
到数据之后,InMemoryCache
对查询来的数据进行分割成单个的对象并保存。
而且为这些单个的对象都设置唯一的标识符,如果在query
数据时将那些可以作为唯一标识符的字段例如id
也一并获取到了,那么就将这个id
作为分割后对象的唯一标识符。
上面这个简单的例子说明,如果id
相同,那么score在
缓存中的数据也会自动进行更新。
因此结合我们之前的实例做一个简单的更改:
export const UPDATE_PERSON_SETTING = gql`
mutation updatePersonById($input: UpdatePersonByIdInput!) {updatePersonById(input: $input) {clientMutationIdperson {idhideSpeaker}}
}
`
我们在进行mutation
之后的返回值中存在id
,这就符合上面的要求。他就会自动进行缓存的更新。
如果你还心存疑虑,你大可在readQuery
后将data
输出一下,此时你就会发现 hideSpeaker
已经更改成目前的状态true
。这就是自动更新的快捷之处。此时你就不必使用readQuery和writeQuery
这种费时费力的方法了。
三:最后的话
1:不论是自动更新还是手动更新,都必须将更改之后的数据返回出来,就像hideSpeaker
,更改他之后,你必须将它返回出来。这不论是在自动更新还是在手动更新上都是有必要的。
2:关于两者的选择使用,毫无疑问,通常情况下使用自动更新,特殊情况下使用手动更新,在明白原理后,有时你可以使用手动更新进行一些投机取巧的更新缓存的操作。
3:难,都难。爬,一起爬。
React Native项目使用react-apollo实现更新缓存的两种方式相关推荐
- java实现mysql自动更新创建时间与更新时间的两种方式
一:通过数据库自身实现 1 .创建表的时候加上 create_time 与 update_time 两个字段 `create_time` timestamp NOT NULL DEFAULT ...
- Python pip更新教程(两种方式)
1. 直接采用命令行模式更新 1.1 搜索框搜索cmd,然后以管理员模式打开 1.2 执行命令 python -m pip install --upgrade pip 1.3 查看更新后的版本 pip ...
- React native 项目进阶(redux, redux saga, redux logger)
之前利用知乎日报的api写了react-native的一个入门项目,传送文章地址React Native 项目入门和源码地址RN入门项目源码,目前github上的代码已经在原文的基础上增加了新的功能, ...
- [置顶] 【稀饭】react native 实战系列教程之热更新原理分析与实现
很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...
- react native 实战系列教程之热更新原理分析与实现
很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...
- React Native 项目整合 CodePush 完全指南
作者 | 钱凯 杏仁移动开发工程师,前嵌入式工程师,关注大前端技术新潮流. 本文使用的环境: React@16.3.1 React Native@0.55.4 react-native-code-pu ...
- 【腾讯Bugly干货分享】React Native项目实战总结
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 "8小时内拼工作,8小 ...
- React Native 项目常用第三方组件汇总
React Native 项目常用第三方组件汇总 https://www.jianshu.com/p/d9cd9a868764?utm_campaign=maleskine&utm_conte ...
- 技术实践丨React Native 项目 Web 端同构
摘要:尽管 React Native 已经进入开源的第 6 个年头,距离发布 1.0 版本依旧是遥遥无期."Learn once, write anywhere",完全不影响 Re ...
最新文章
- The Human Touch 将人工智能和机器人用于病人工作的实际和伦理意义
- iframe 父页面与子页面之间的方法的相互调用
- dNet项目数据访问层代码总结
- 数据库原理与应用(SQL Server)笔记 第九章 存储过程和触发器
- 《Linux内核原理与分析》第六周作业
- linux系统监控和进程管理
- All Of ACM
- 力扣283,移动零(JavaScript)
- Lucas(卢卡斯)定理
- 手机APP测试主要有哪些内容
- linux更新系统内核,Linux内核升级方法详解
- 如何建立个人网站:从搭建到运营再到盈利
- 怎么设置计算机升级更新失败怎么办,windows update更新失败怎么办,教您windows update更新失败怎么办...
- 2016书单总结--看透SpringMvc源代码分析与实践-概述
- Unity出IOS包报错记 -1
- Python基础进阶
- Atom终端命令行插件
- 半同步半异步模式以及Leader_Follwer模式
- 2023CUPT第七题 法拉第波 思路和解法
- 2023全新个人免签约码支付系统PHP源码+ThinkPHP6框架/全开源的