react全局状态管理_rxv: 在React中用Vue3的reactivity包实现状态管理。

前言

React的状态管理是一个缤纷繁杂的大世界,光我知道的就不下数十种,其中有最出名immutable阵营的redux,有mutable阵营的mobxreact-easy-state,在hooks诞生后还有极简主义的unstated-next,有蚂蚁金服的大佬出品的hoxhoox

其实社区诞生这么多种状态管理框架,也说明状态管理库之间都有一些让人不满足的地方。

rxv是我依据这些痛点,并且直接引入了Vue3的package: @vue/reactivity去做的一个React状态管理框架,下面先看一个简单的示例:

示例

// store.ts
import { reactive, computed, effect } from '@vue/reactivity';export const state = reactive({count: 0,
});const plusOne = computed(() => state.count + 1);effect(() => {console.log('plusOne changed: ', plusOne);
});const add = () => (state.count += 1);export const mutations = {// mutationadd,
};export const store = {state,computed: {plusOne,},
};export type Store = typeof store;
// Index.tsx
import { Provider, useStore } from 'rxv'
import { mutations, store, Store } from './store.ts'
function Count() {const countState = useStore((store: Store) => {const { state, computed } = store;const { count } = state;const { plusOne } = computed;return {count,plusOne,};});return (<Card hoverable style={{ marginBottom: 24 }}><h1>计数器</h1><div className="chunk"><div className="chunk">store中的count现在是 {countState.count}</div><div className="chunk">computed值中的plusOne现在是 {countState.plusOne.value}</div><Button onClick={mutations.add}>add</Button></div></Card>);
}export default () => {return (<Provider value={store}><Count /></Provider>);
};

可以看出,store的定义只用到了@vue/reactivity,而rxv只是在组件中做了一层桥接,连通了Vue3和React,正如它名字的含义:React x Vue。

一些痛点

根据我自己的看法,我先简单的总结一下现有的状态管理库中或多或少存在的一些不足之处:

  1. redux为代表的,语法比较冗余,样板文件比较多。
  2. mobx很好,但是也需要单独的学一套api,对于react组件的侵入性较强,装饰器语法不稳定。
  3. unstated-next是一个极简的框架,对于React Hook做了一层较浅的封装。
  4. react-easy-state引入了observe-util,这个库对于响应式的处理很接近Vue3,我想要的了。

下面展开来讲:

options-based的痛点

Vuex和dva的options-based的模式现在看来弊端多多。具体的可以看尤大在vue-composition-api文档中总结的。

简单来说就是一个组件有好几个功能点,但是这几个功能点在分散在data,methods,computed中,形成了一个杂乱无章的结构。

当你想维护一个功能,你不得不先完整的看完这个配置对象的全貌。

心惊胆战的去掉几行,改掉几行,说不定会遗留一些没用的代码,也或者隐藏在computed选项里的某个相关的函数悄悄的坑了你...

而hook带来的好处是更加灵活的代码组织方式。

redux

直接引入dan自己的吐槽吧,要学的概念太多,写一个简单的功能要在五个文件之间跳来跳去,好头疼。redux的弊端在社区被讨论也不是一天两天了,相信写过redux的你也是深有同感。

ace7f47d920b5e799102ce13b85244b3.png

unstated-next

unstated-next其实很不错了,源码就40来行。最大程度的利用了React Hook的能力,写一个model就是写一个自定义hook。但是极简也带来了一些问题:

  1. 模块之间没有相互访问的能力。
  2. Context的性能问题,让你需要关注模块的划分。(具体可以看我这篇文章的性能章节
  3. 模块划分的问题,如果全放在一个Provider,那么更新的粒度太大,所有用了useContext的组件都会重复渲染。如果放在多个Provider里,那么就会回到第一条痛点,这些模块之间是相互独立的,没法互相访问。
  4. hook带来的一些心智负担的问题。React Hooks 你真的用对了吗?

react-easy-state

这个库引入的observe-util其实和Vue3 reactivity部分的核心实现很相似,关于原理解析也可以看我之前写的两篇文章:带你彻底搞懂Vue3的Proxy响应式原理!TypeScript从零实现基于Proxy的响应式库。带你彻底搞懂Vue3的Proxy响应式原理!基于函数劫持实现Map和Set的响应式。

  1. 似乎不维护了。
  2. 对于异步队列的处理过于hack,带来了很多issue,而且一直没有解决。

那其实转而一想,Vue3 reactivity其实是observe-util的强化版,它拥有了更多的定制能力,如果我们能把这部分直接接入到状态管理库中,岂不是完全拥有了Vue3的响应式能力。

原理分析

vue-next是Vue3的源码仓库,Vue3采用lerna做package的划分,而响应式能力@vue/reactivity被划分到了单独的一个package中

从这个包提供的几个核心api来分析:

effect

effect其实是响应式库中一个通用的概念:观察函数,就像Vue2中的Watcher,mobx中的autorunobserver一样,它的作用是收集依赖

它接受的是一个函数,这个函数内部对于响应式数据的访问都可以收集依赖,那么在响应式数据更新后,就会触发响应的更新事件。

reactive

响应式数据的核心api,这个api返回的是一个proxy,对上面所有属性的访问都会被劫持,从而在get的时候收集依赖(也就是正在运行的effect),在set的时候触发更新。

ref

对于简单数据类型比如number,我们不可能像这样去做:

let data = reactive(2)
//  oops
data = 5

这是不符合响应式的拦截规则的,没有办法能拦截到data本身的改变,只能拦截到data身上的属性的改变,所以有了ref。

const data = ref(2)
//  ok
data.value= 5

computed

计算属性,依赖值更新以后,它的值也会随之自动更新。其实computed内部也是一个effect。

拥有在computed中观察另一个computed数据、effect观察computed改变之类的高级特性。

实现

从这几个核心api来看,只要effect能接入到React系统中,那么其他的api都没什么问题,因为它们只是去收集effect的毅力,去通知effect触发更新。

effect接受的是一个函数,而且effect还支持通过传入schedule参数来自定义依赖更新的时候需要触发什么函数,

rxv的核心api: useStore接受的也是一个函数selector,它会让用户自己选择在组件中需要访问的数据。

那么思路就显而易见了:

  1. selector包装在effect中执行,去收集依赖。
  2. 指定依赖发生更新时,需要调用的函数是当前正在使用useStore的这个组件的forceUpdate强制渲染函数。

这样不就实现了数据变化,组件自动更新吗?

简单的看一下核心实现

export const useStore = <T, S>(selector: Selector<T, S>): S => {const forceUpdate = useForceUpdate();const store = useStoreContext();const effection = useEffection(() => selector(store), {scheduler: forceUpdate,lazy: true,});const value = effection();return value;
};
  1. 先通过useForceUpdate在当前组件中注册一个强制更新的函数。
  2. 通过useContext读取用户从Provider中传入的store。
  3. 再通过Vue的effect去帮我们执行selector(store),并且指定scheduler为forceUpdate,这样就完成了依赖收集。

就简单的几行代码,就实现了在React中使用@vue/reactivity中的所有能力。

优点:

  1. 直接引入@vue/reacivity,完全使用Vue3的reactivity能力,拥有computed, effect等各种能力,并且对于Set和Map也提供了响应式的能力。后续也会随着这个库的更新变得更加完善的和强大。
  2. vue-next仓库内部完整的测试用例。
  3. 完善的TypeScript类型支持。
  4. 完全复用@vue/reacivity实现超强的全局状态管理能力。
  5. 状态管理中组件级别的精确更新。
  6. Vue3总是要学的嘛,提前学习防止失业!

缺点:

  1. 由于需要精确的收集依赖全靠useStore,所以selector函数一定要精确的访问到你关心的数据。甚至如果你需要触发数组内部某个值的更新,那你在useStore中就不能只返回这个对象本身。

源码地址

https://github.com/sl1673495/react-composition-api

如果你喜欢这个库,欢迎给出你的star✨,你的支持就是我最大的动力~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS Code 变身约会利器!以码会友,轻松找到心仪的TA!

在韩老师的《Visual Studio Code 权威指南》一书中&#xff0c;我向大家推荐了许多好用的插件&#xff0c;其中也不乏许多摸鱼插件&#xff0c;刷知乎、炒股票、看电影、听音乐、追番、看小说&#xff0c;一应俱全。前不久&#xff0c;韩老师还给大家推荐过一款“小霸王”插件&…

机器学习——常用算法的总结

机器学习常用算法总结 机器学习——常用算法的总结学习方式一、监督式学习&#xff1a;1、分类2、回归补充——线性回归与逻辑回归二、非监督式学习&#xff1a;三、半监督式学习&#xff1a;四、强化学习&#xff1a;算法类似性一、回归算法&#xff1a;二、基于实例的算法三、…

机器学习——决策树学习

机器学习——决策树学习一、什么是决策树二、决策树的学习过程特征选择&#xff1a;决策树生成&#xff1a;剪枝&#xff1a;三、决策树的一个具体的实例导入数据python strip() 函数和 split() 函数的详解及实例数据处理提取到训练集中的标签给数据的每一列添加上标签&#xf…

微软:Excel公式是世界上使用最广泛的编程语言

喜欢就关注我们吧&#xff01;文|一君微软近日推出了一项 Excel 公式构建的新功能 LAMBDA&#xff0c;正则测试阶段。LAMBDA 允许使用 Excel 自身的公式语言自定义功能&#xff0c;而过去&#xff0c;Excel 中需要通过 JS 等语言编写自定义函数。同时&#xff0c;LAMBDA 还可以…

机器学习——文件的读取

机器学习——文件的读取(一).txt文件的读取(二)excel文件读取操作(一).txt文件的读取 txt的链接 链接&#xff1a;https://pan.baidu.com/s/1fIAUdCDTpR7TiqLHZtx1yg 提取码&#xff1a;0929 python strip() 函数和 split() 函数的详解及实例 一直以来都分不清楚strip和split…

linux select读取节点数据失败_MySQL中覆盖索引查询和select*查询执行结果案例分析...

索引优化建议在MySQL中要尽可能使用覆盖索引进行检索&#xff0c;只访问索引的查询(索引列和查询列一致)&#xff0c;减少select * 可提高查询效率覆盖索引(Covering Index)理解方式一:就是select的数据列只用从索引中就能够取得&#xff0c;不必读取数据行&#xff0c;MySQL可…

使用 Azure WAF 羞辱黑客的智商

点击上方蓝字关注“汪宇杰博客”导语还记得之前给大家介绍过的《使用 Azure Web 应用防火墙拦截黑客攻击》吗&#xff1f;今天我又带来了一个有趣的 Azure WAF 小技巧&#xff0c;可以让你爽一把。好奇的黑客今天 Azure Application Insights 上发现了一段集中时间的404错误&am…

机器学习之乳腺癌问题(SVM)

机器学习之乳腺癌问题SVM题目所需的代码及数据利用SVM建模SVM调参题目所需的代码及数据 链接&#xff1a;https://pan.baidu.com/s/1bS7Ku_PUfcimiVkmLz9Fzw 提取码&#xff1a;0929 利用SVM建模 import matplotlib.pyplot as plt import pandas as pd import numpy as npfro…

如何将日志记录到 Windows事件日志 中

每当出现一些未捕获异常时&#xff0c;操作系统都会将异常信息写入到 Windows 事件日志 中&#xff0c;可以通过 Windows 事件查看器 查看&#xff0c;如下图&#xff1a;这篇文章将会讨论如何使用编程的方式将日志记录到 Windows 事件日志 中。安装 EventLog 要想在 .NET Core…

【Java】springboot

文章目录 Spingboot1、起步依赖2、构建springboot工程jar包3、springboot配置文件4、多环境配置5、maven和boot多环境兼容问题6、配置文件分类7、springboot整合mybatis Spingboot springboot用来简化spring的初始搭建以及开发过程。 比方说&#xff0c;创建一个springmvc程序…

数据科学与python语言——Matplotlib数据可视化基础

Matplotlib数据可视化基础一.读取数据与数据处理阶段1.提取指定行中的数据2.得到>指定数值的数据3.得到指定值得数据4.整体的数据处理&#xff1a;二.画图函数1.plt.subplots()2.plt.subplots_adjust()3.设置x轴y轴的刻度和标签4.使用中文标题在作图时三.画折线图(plot)四.画…

2021年,Azure云遇到. NET5,注定开启高光时刻,微软的心,真大!

云开发诞生的市场背景云开发是一个已经存在了很多年的概念&#xff0c;但在过去未能真正成为主流。然而&#xff0c;由于云和软件即服务的宏观趋势的结合&#xff0c;以及技术的进步&#xff0c;如容器技术 Docker 和 Kubernetes&#xff0c;云开发现在有机会最终成为基于云的应…

.net5+nacos+ocelot 配置中心和服务发现实现

相关文章&#xff1a;手动造轮子——为Ocelot集成Nacos注册中心出处&#xff1a;https://www.cnblogs.com/buruainiaaaa/p/14121176.html作者&#xff1a;唐 最近一段时间 因公司业务需要&#xff0c;需要使用.net5做一套微服务的接口&#xff0c;使用nacos 做注册中心和配置中…

数据科学与python语言——Pandas统计分析基础(时间转换+聚合)

Pandas统计分析基础&#xff08;时间转换聚合&#xff09;实验要求一实验二要求全部代码实验要求一 #M表的时间戳类型转为datetime data_Mete[TIMESTAMP]pd.to_datetime(data_Mete[TIMESTAMP],format%Y%m%d%H%M%S)data_VI[Date]pd.to_datetime(data_VI[Date],format%Y/%m/%d) p…

容器的那点事

当我们的后端服务器不够用的时候&#xff0c;我们可以通过容器技术&#xff0c;可以快速的把这些服务器全部虚拟出来&#xff0c; 当然这个虚拟跟虚拟机是不一样的&#xff0c;比虚拟机的方式快多了&#xff0c;早期阿里的淘宝平台如果整个坏掉了&#xff0c;重新搭建部署起来需…

lqb——修改数组

思路 **常规思路用哈希表的思想,设置bool数组标识是否被占用过,但是发生矛盾时将会造成查找需要遍历整个数组,比如,1,2,3……100000已连续占用,此时再插入1,将会一直遍历这100000个数,极端情况下,插入100000个1,将是n平方的复杂度。 如何快速查找到插入位置,这就引…

bp神经网络训练_数据分析模型6——神经网络基础(人工智能的底层模型)

未经许可请勿转载更多数据分析内容参看这里今天我们来学习人工智能的底层模型——神经网络&#xff08;NEURAL NETWORKS&#xff09;&#xff0c;现在比较热门的一个模型是深度学习&#xff0c;深度学习的基础也是神经网络&#xff0c;要学好深度学习&#xff0c;神经网络不了解…

四种最令人讨厌的编程语言:Java、Javascript、C++和Perl

喜欢就关注我们吧&#xff01;TIOBE 12 月榜单已于日前公布&#xff0c;在最新的排行榜中&#xff0c;C 语言仍高居榜首&#xff0c;其次分别是 Java、Python 和 C。在编程语言这一领域中&#xff0c;许多编程语言都会随着时间的推移而经历人气的激增&#xff0c;以及历史迭代之…

微软用的工具,统一财务三大表及高级分析通用模板

虽然罗叔并非财务专业&#xff0c;但大概了解一些财务常识。例如财务报表的三大报表以及一些常见分析等。本月《BI真经》视频课程即将就绪&#xff0c;后续罗叔将和大家开展更多的业务研究。我们知道&#xff0c;PowerBI 在绘制某些报告时候很难&#xff0c;初学者根本无法实现…

文件 单片机_如何查看你写的单片机程序有多大?

单片机我们都用过&#xff0c;我们知道单片机的FLASH有4K的&#xff0c;有8K的&#xff0c;单片机程序我们也写过&#xff0c;但是我们写好的程序有多大&#xff0c;你知道吗&#xff1f;程序写好并编译后生成hex文件&#xff0c;这个hex文件就是要下载到单片机里的文件&#x…