为什么react-redux没有更新hooks API

栏目: 服务器 · 发布时间: 5年前

内容简介:按照正常来讲,像 React-Redux 这一类较为活跃的社区类库,在 React 有较大的更新出现的时候一般都会及时跟进的。而这一次 React 的 Hooks 发布,有将近两个月的 beta 期,以及到截止本篇文章发布已经 Hooks 正式版也已经将近一个月来,React-Redux 到现在都没有正式发布一个类似去年年底,出于兴趣,研究了一波 redux 和 react-redux 的源码,除了在原理上的理解之外,让我较为好奇的一点就是:这样的代码是非常可以理解的,而且也是非常符合 Hooks 的使用习

按照正常来讲,像 React-Redux 这一类较为活跃的社区类库,在 React 有较大的更新出现的时候一般都会及时跟进的。而这一次 React 的 Hooks 发布,有将近两个月的 beta 期,以及到截止本篇文章发布已经 Hooks 正式版也已经将近一个月来,React-Redux 到现在都没有正式发布一个类似 useRedux 这样的 Hooks API,那么这是为什么呢?我们来分析一下原因。

去年年底,出于兴趣,研究了一波 redux 和 react-redux 的源码,除了在原理上的理解之外,让我较为好奇的一点就是: React-Redux 到目前为止都没有对 Hooks 进行支持。从使用角度上来讲,出现一个类似:

function ConnectedComponent() {
  const store = useReduxStore()
  const state = useRedux(function mapState())
}
复制代码

这样的代码是非常可以理解的,而且也是非常符合 Hooks 的使用习惯的,事实上社区上也出现来很多非官方的 reudx Hooks 的类库:

说明了总体上社区对于 Hooks 的接受度是很高的,大家应该都在期待官方能给出一个真正的 Hooks API。那么为什么 React-Redux 到现在都没有发布正式的 Hooks API 呢?

在翻阅 React-Redux 的 issues 列表的时候,我发现了 这个 issue 。作者非常完整得为我们介绍了 React-Redux 从最初得 idea 到现在 v6 版本得成长历程。那么 v6 版本相比 v5 版本有哪些大的变化呢?

createContext
Provider
connect

v6 版本更新这些内容的主要原因如下:

  • 老的 context API 即将被删除,并且如果和新的 context API 一起使用会有问题
  • React 即将推出 Concurrent Mode 异步渲染,如果使用老的方式可能会导致不同的子树获取的状态不同,使用新的 context API,React 会确保整棵树拿到的是相同的状态
  • createContext 默认带有 top-down 数据流,不再需要 React-Redux 自己实现

以上是 v6 版本的变化和其原因,但是到目前为止我们好像并没有看到任何提及 Hooks 的地方。别急,接下去就是正题了。

在升级到 v6 的过程中,React-Redux 团队发现 v6 版本的整体性能是比不上 v5 的。这个性能下降的主要原因不是 React-Redux 的实现代码有什么问题,其主要问题是来自 createContent 的实现方式,以及 React-Redux 选择了只有在 Provider 中订阅 store 变化。

注意

React-Redux 选择使用 createContext 和只有在 Provider 中订阅都是没有任何问题的,也是 React 官方推荐的使用方法,从面向未来的眼光来看,这是势必的升级。所以同学们在后面分析问题的时候不要问,为什么不换个实现方式啥的。

那么所谓的性能问题具体是怎么来的呢?**主要原因是 createContext 在 value 变化的时候他是如何通知子树的。**我们先来看一组性能测试对比图:

为什么react-redux没有更新hooks API

这个测试用例来自 react-redux-benchmarks ,大家有兴趣可以自己去跑一下。

从图中我们可以看出来,v6 主要性能降低的点是来自于 Scripting ,也就是运行 JavaScript 脚本的时间,从数据上来看,是 v5 版本的两倍多。虽然在 RenderingPainting 阶段要好很多,但是因为 Scripting 的占比最大,所以总体上讲是略微有些下降的。

**其根本原因是 createContext 的实现方式中,我们更改了 Provider 的 value,那么在这次更新周期中,React 会遍历 Provider 的所有子节点,并对监听了这一个 context 的节点进行标记,让后续渲染中知道这个节点是需要更新的,即便他的 props 和 state 根本没有变化。**关于为什么 React 要这么去实现的原因不是一句话能讲完的,他涉及到 React 16 之后 Fiber 判断一个节点是否有更新的方法,后面我会单独写一篇文章来讲解,现在大家只需要知道他就是这么实现的就可以了。

因为上诉的原因,我们可以想象在一个节点非常多的 React 应用中,一个类似 React-Redux 这样放置在最顶层的 Provier 数据变化之后,他的总体计算量肯定是非常大的。

相对的,在 v5 中因为使用老的 context API,为了避免一些这个 API 带来的问题,所以 React-Redux 团队选择在 connect 返回的 WrapperComponent HOC 中进行 store 数据变化的监听,也就是说 Store 变化之后之后被 connect 的组件可能出现 props 上的变化,而没有任何需要遍历子树的需要。

以上就是 v6 版本在性能上不升反降的原因。这也是 React 新的 context API 不是很适合用在变化频繁的数据上原因。我们可以想象如果我们像以前一样把一个表单的所有项数据都缓存在 redux store 里面,每次输入都要更新 store,可能带来的对整体性能的影响。关于这一块,React 也有一个 issue 在讨论是否以及如何设计一个方案来解决这个性能上的问题。这个讨论非常热闹,大家有兴趣可以关注一下。

那么到现在为止我们还是没有讲到 Hooks 相关的任何内容,是不是有点偏题了?不,因为我们已经知道了大部分的原因,那就是新的 context API 存在的性能问题。而这个问题,反应到 Hooks 上面,则会更大程度地体现出来。

如果我们要封装一个类似 useRedux 这样的 Hook,那么我们肯定需要用到 useContext 来获取 Provider 提供的 state,毕竟 Provider 是唯一订阅来 store 变化的。而使用了 useContext ,就代表我们这个组件是 依赖于 这个 context 的,也就是说一旦 state 变化,这个组件就会被标记为 需要更新

而按照我们一直以来的使用 React-Reudx 的情况,我们都会提供 mapState 来映射组件真正需要监听的数据,因为 store 是整个应用的,不太会存在某一个组件需要整个应用所有的数据的情况。这种情况下,在 v5 版本中,甚至是在 v6 版本中使用 connect 的情况,都会在 HOC 中进行 mapState 的执行进行数据映射,然后通过 shallowEqual 判断是否有依赖的 state 变化,如果没有其实是不需要更新真正的组件的。

但是在使用 useContext 的情况,即便我们给 useRedux 提供来 mapState ,但是他的执行依然要等到这个组件真正开始执行更新的时候。也就是说我们无法让 React 在更新这个组件之前就判断他是否可以不被更新,那么 React 提供的优化就没啥用了。

而同时一旦我们的组件开始执行,即便我们发现 useRedux 返回的 map 之后的 state 其实跟上一次是一样的,我们也无法告诉 React 这个组件其实是不需要更新的来终止这次更新。所以,这是一个无法在**类库层面进行的优化。**要优化我们只有通过使用者自己使用 useMemo 这样的 API,那么对于开发经验不是那么多的同学,很可能会导致这个组件会被频繁进行无用更新,而导致性能浪费。

那么以上就是为什么 React-Redux 以及很多常用类库还没有更新 Hooks API 的原因来,目前来说这个性能问题较为无解,React 官方也在考虑是否要出一些新的 context 相关的 API 来专门优化更新频率较高的情况,我们也只能拭目以待了。

目前来说,如果你不清楚 createContent 的这些问题,建议不要把经常需要更新的内容放在 context 里面(除非没有别的方法)。

以上,就是我对于为什么 Hooks 现在呼声这么高,但是社区支持却没有这么快跟进的原因分析,如果有任何问题,可以直接回复邮件,或者在我的 AMA(Ask Me Anything) 中给我提问,我都会浏览,并且进行解答。

另外在这里提出的一些问题,也会在后续进行更详细的解析:

createContext

我是Jocky,如果对于我分析的React内容感兴趣,可以订阅我,我会保持对React生态更新及时跟进,以及对React及其生态的内容进行深度解析。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

八年级数学(华东师大版)-解题升级-解题快速反应一本通(新课标)

八年级数学(华东师大版)-解题升级-解题快速反应一本通(新课标)

孙丽敏等编 / 吉林教育出版社 / 2004-6 / 10.0

本书将与知识点、重点、难点和考点有关的典型题做全析全解,是具有解题题典性质的助学读物。但本书又优于解题题典,不仅展示解题过程,更详细地提供了解题思考过程和切入点的选择方法,教方法导引思路的功能更强。 学生要提高解题能力,必须具备两个条件:一是打好基础,二是能够运动所学知识分析问题和解决问题。本书用例题解析解说知识点、重点、难点和考点,同时提供解题思考过程,在打基础中激活能力,在解题实......一起来看看 《八年级数学(华东师大版)-解题升级-解题快速反应一本通(新课标)》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具