精读《react-easy-state 源码》
1. 引言react-easy-state 是个比较有趣的库,利用 Proxy 创建了一个非常易用的全局数据流管理方式。 import React from "react"; import { store,view } from "react-easy-state"; const counter = store({ num: 0 }); const increment = () => counter.num++; export default view(() => <button onClick={increment}>{counter.num}</button>); 上手非常轻松,通过 当然,为了实现这一点,需要对所有组件包裹一层 2. 精读这个库利用了 nx-js/observer-util 做 Reaction 基础 API,其他核心功能分别是 Reaction这个单词名叫 “反应”,是实现双向绑定库的最基本功能单元。 拥有最基本的两个单词和一个概念: import { observable,observe } from "@nx-js/observer-util"; const counter = observable({ num: 0 }); const countLogger = observe(() => console.log(counter.num)); // 会自动触发 countLogger 函数内回调函数的执行。 counter.num++; 在第 35 期精读 精读《dob - 框架实现》 “抽丝剥茧,实现依赖追踪” 一节中有详细介绍实现原理,这里就不赘述了。 有了一个具有反应特性的函数,与一个可以 “触发反应” 的对象,那么实现双向绑定更新 View 就不远了。 storereact-easy-state 的 import React from ‘react‘ import { view,store } from ‘react-easy-state‘ export default view(() => { const counter = store({ num: 0 }) const increment = () => counter.num++ return <button={increment}>{counter.num}</div> }) 所以当监测到在 React 组件内部创建 return useMemo(() => observable(obj),[]); 这是因为 React Hooks 场景下的 Function Component 每次渲染都会重新创建 Store,会导致死循环。因此利用
view根据 Function Component 与 Class Component 的不同,分别进行两种处理,本文主要介绍对 Function Component 的处理方式,因为笔者推荐使用 Function Component 风格。 首先最外层会套上 return memo(/**/); 然后构造一个 const [,forceUpdate] = useState(); 之后,只要利用
所以作者通过 const render = useMemo( () => observe(Comp,{ scheduler: () => setState({}),lazy: true }),[] ); return render; 最后别忘了在组件销毁时取消监听: useEffect(() => { return () => unobserve(render); },[]); batch这也是双向绑定数据流必须解决的经典问题,批量更新合并。 由于修改对象就触发渲染,这个过程太自动化了,以至于我们都没有机会告诉工具,连续的几次修改能否合并起来只触发一次渲染。 尤其是 For 循环修改变量时,如果不能合并更新,在某些场景下代码几乎是不可用的。 所以 import React from "react"; import { view,store,batch } from "react-easy-state"; const user = store({ name: "Bob",age: 30 }); function mutateUser() { // this makes sure the state changes will cause maximum one re-render,// no matter where this function is getting invoked from batch(() => { user.name = "Ann"; user.age = 32; }); } export default view(() => ( <div> name: {user.name},age: {user.age} </div> ));
export function batch(fn,ctx,args) { let result; unstable_batchedUpdates(() => (result = fn.apply(ctx,args))); return result; } 利用 同时代码里还对 4. 总结好了,
如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
special Sponsors
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |