在 React Hooks 状态管理方案中,通常会遇到联动更新的问题:
同一模块更新,消费了此模块的组件都会 re-render,即使被更新的 state 在组件中未用到。
例如 model = { a: 1, b: 2, fn: () => {} }
,调用 setModel({ a: 2 })
,只使用 b
的组件也会 re-render 。而只使用 fn
函数的组件,理论上永远不应被 setModel()
触发更新,但也会 re-render 。
若不想被关联更新,就得将数据拆的足够细 —— 例如 React.useState()
jotai
等,便是这种 "元数据" 思路。而同时还存在另一种 "模块化" 思路,例如 React.useReducer()
,希望将同一模块的数据放在一起。
使用 "元数据",会背离将数据放在同一 model 的初衷,使用 "模块化",又面临着组件联动更新的问题。
使用 Redux 的传统 class 组件项目中,react-redux
实现了对组件联动更新的性能优化。但纯粹的 React Hooks 项目,只使用 Hooks 实现的状态管理器,却没有一个好的解决方案。
flooks 是一个专用于 React Hooks 的状态管理器,API 极其简单。即支持模块化,又支持模块间的互通,可能是最简单的一个。
→ https://github.com/nanxiaobei/flooks
之前 flooks v3 的 API 是这样的:
const counter = (now) => ({
count: 0,
add() {
const { count } = now();
now({ count: count + 1 });
},
});
function Counter() {
const { count, add } = useModel(counter, ['count']); // 借助 deps 知晓注入的 state
return <div />;
}
flooks v4 做了一些更新:
const counter = ({ get, set }) => ({
count: 0,
add() {
const { count } = get(); // get
set({ count: count + 1 }); // set
},
});
function Counter() {
const { count, add } = useModel(counter); // 再不需要 deps
return <div />;
}
主要改变是:
now
分为 get
与 set
,以让代码更清晰set
支持函数形式 set(state => ({ count: state.count + 1 })
除了 API 更新,更重要的是,flooks v4 将背后的更新核心逻辑进行了全部重写,彻底解决了 "模块化" 方案联动更新的问题,从而实现了对更新颗粒度的精细控制。
借助 proxy
,flooks 实现了惊人的自动优化,完全按需 re-render,React 真正变为 "react"。
useModel(someModel)
返回一个 proxy,只有真正用到的数据,才会注入组件,若未用到,则不会注入。
因此无需再添加 deps,因为 useModel()
现在已经可以知道,哪些数据会被解构出来使用,从而只更新用到的数据。
const { fn1, fn2 } = useModel(someModel); // A 组件
const { b, setB } = useModel(someModel); // B 组件
setB(); // A 无 re-render
若 A 中只使用函数,则其它组件更新不触发 A re-render 。
const { a } = useModel(someModel); // A 组件
const { b, setB } = useModel(someModel); // B 组件
setB(); // A 无 re-render
若 A 中未使用某些 state,则其它组件更新不触发 A re-render 。
const { someFn } = useModel(someModel); // A 组件
someFn(); // 无 someFn.loading,无额外 re-render
若 A 中未使用 someFn.loading
,someFn()
不触发额外 re-render 。
若 someFn
为异步,普通 loading 方案中,即使 somefn.loading
未用到,re-render 也会触发至少两次(先 true
然后 false
)。但使用 flooks,若 somefn.loading
未用到,则完全不会存在隐形 loading 更新。
以上,flooks v4 真正实现了 React Hooks 状态管理方案的 "模块化"。
即可以将同一模块的数据放在一处,方便统一管理,又不用担心局部更新触发联动更新。更新完全是按需进行,只有用到的数据,才触发更新,未用到的数据,即使是 someFn.loading
,也不会注入组件。
在代码中写出来的,就是会更新的,没有写的,就根本不会存在,再不用担心更新问题。
一切都是如此符合直觉,再无其它烦人概念。
flooks v4,喜欢的话,欢迎 ✰
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.