flooks v4,自动优化,按需更新。最简单 React Hooks 状态管理器 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nanxiaobei
V2EX    React

flooks v4,自动优化,按需更新。最简单 React Hooks 状态管理器

  •  
  •   nanxiaobei
    nanxiaobei 2021-07-28 12:54:13 +08:00 2317 次点击
    这是一个创建于 1605 天前的主题,其中的信息可能已经有所发展或是发生改变。

    状态管理的难题

    在 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 v4 介绍

    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 分为 getset,以让代码更清晰
    • 无需再传入 deps 进行 re-render 控制
    • set 支持函数形式 set(state => ({ count: state.count + 1 })

    除了 API 更新,更重要的是,flooks v4 将背后的更新核心逻辑进行了全部重写,彻底解决了 "模块化" 方案联动更新的问题,从而实现了对更新颗粒度的精细控制。

    Re-render 自动优化方案

    借助 proxy,flooks 实现了惊人的自动优化,完全按需 re-render,React 真正变为 "react"。

    useModel(someModel) 返回一个 proxy,只有真正用到的数据,才会注入组件,若未用到,则不会注入。

    因此无需再添加 deps,因为 useModel() 现在已经可以知道,哪些数据会被解构出来使用,从而只更新用到的数据。

    只使用函数绝不触发 re-render

    const { fn1, fn2 } = useModel(someModel); // A 组件 const { b, setB } = useModel(someModel); // B 组件 setB(); // A 无 re-render 

    若 A 中只使用函数,则其它组件更新不触发 A re-render 。

    未使用的 state 绝不触发 re-render

    const { a } = useModel(someModel); // A 组件 const { b, setB } = useModel(someModel); // B 组件 setB(); // A 无 re-render 

    若 A 中未使用某些 state,则其它组件更新不触发 A re-render 。

    未使用的 loading 绝不触发 re-render

    const { someFn } = useModel(someModel); // A 组件 someFn(); // 无 someFn.loading,无额外 re-render 

    若 A 中未使用 someFn.loadingsomeFn() 不触发额外 re-render 。

    someFn 为异步,普通 loading 方案中,即使 somefn.loading 未用到,re-render 也会触发至少两次(先 true 然后 false)。但使用 flooks,若 somefn.loading 未用到,则完全不会存在隐形 loading 更新。

    真正的 "模块化"

    以上,flooks v4 真正实现了 React Hooks 状态管理方案的 "模块化"。

    即可以将同一模块的数据放在一处,方便统一管理,又不用担心局部更新触发联动更新。更新完全是按需进行,只有用到的数据,才触发更新,未用到的数据,即使是 someFn.loading,也不会注入组件。

    在代码中写出来的,就是会更新的,没有写的,就根本不会存在,再不用担心更新问题。

    一切都是如此符合直觉,再无其它烦人概念。

    结束啦

    flooks v4,喜欢的话,欢迎

    https://github.com/nanxiaobei/flooks

    6 条回复    2021-07-30 11:53:00 +08:00
    qfdk
        1
    qfdk  
    PRO
       2021-07-28 13:01:48 +08:00 via iPhone
    感觉好像很不错 等假期回来
    powerfulyang
        2
    powerfulyang  
       2021-07-28 14:51:09 +08:00
    @umijs/plugin-model 这两个看起来好像
    nanxiaobei
        3
    nanxiaobei  
    OP
       2021-07-28 15:29:15 +08:00
    @qfdk #1
    nanxiaobei
        4
    nanxiaobei  
    OP
       2021-07-28 15:29:46 +08:00
    @powerfulyang #2 完全不一样,只是名字里都带 "model","model" 这个名词是 rematch 发扬光大的
    statumer
        5
    statumer  
       2021-07-30 02:13:15 +08:00 via Android
    感觉楼主的这个 loading 功能不错
    nanxiaobei
        6
    nanxiaobei  
    OP
       2021-07-30 11:53:00 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2617 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 13:18 PVG 21:18 LAX 05:18 JFK 08:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86