useReducer 这个东西到底有啥用, 简单的东西搞复杂化是为了啥? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bthulu
V2EX    React

useReducer 这个东西到底有啥用, 简单的东西搞复杂化是为了啥?

  •  1
     
  •   bthulu 2023-10-22 10:17:25 +08:00 3070 次点击
    这是一个创建于 788 天前的主题,其中的信息可能已经有所发展或是发生改变。

    明明可以每个 action 对应一个函数, ide 里点下 click 的函数名, 立即跳到函数实现, 简单直观. 偏要搞个 reducer, 想看下函数实现, 得先跳到函数, 记下 dispatch 的 type, 再跳到 dispatch, 再跳到 reducer, 再在 reducer 里找 type, 这才算找到函数实现. 严重影响调试速度.

    按官方的说法, 这样做有以下几个好处:

    1. 让所有逻辑都可以存放在一个地方
    2. 有利于代码的调试
    3. 有利于代码的测试

    关于 1, 我将 action 对应的函数都写在一块, 跟用一个函数包起来放在一块, 不都是在一块吗, 有什么区别? 难道是为了避免有人破坏这个默契, 非要将处理函数东放一个西放一个?

    关于 2, 这哪里利于调试了, 简直是调试的噩梦

    关于 3, 确实纯函数方便测试, 这个不可否认. 虽然我从来没写过 reducer 的测试代码.

    19 条回复    2023-10-23 10:38:52 +08:00
    codehz
        1
    codehz  
       2023-10-22 10:28:43 +08:00
    确实 reducer 不是最优的,但这主要是取决于 js 本身的限制,但相比于 state 和一大堆 callback 乱改 state 还是有一定好处的,至少你能从 useReducer 那里看到 state 有可能的变化方式(当然你也可以摆烂只做 setState 一样的事情,那种就不提了),比如限定 state 只能+1 或者-1 ,如果用 setState ,这个意思是无法表达出来的
    不过你这把所有 click 函数都直接 dispatch 的情况,多半还是存在一些问题,相当于另一个方向摆烂,我建议可以放点代码例子来看看是不是这个方向的写法
    某种意义上说可以理解为写了一个状态机,reducer 函数就是状态转移方程,dispatch 则是触发状态转移的 trigger
    hervey0424
        2
    hervey0424  
       2023-10-22 10:46:44 +08:00
    这玩意除了给自己添堵真没啥用, 用起来麻烦, 找起来麻烦
    easychen
        3
    easychen  
       2023-10-22 11:16:41 +08:00
    这个本来就是可选的啊,场景简单的话直接上 mobx 之类就可以了吧。
    paradox8599
        4
    paradox8599  
       2023-10-22 11:38:23 +08:00 via Android
    https://github.com/pmndrs/zustand
    最近在用这个,感觉更舒服一点
    chaxus
        5
    chaxus  
       2023-10-22 12:08:04 +08:00   1
    reducers 是描述 action 如何改变 state 。思想是 Facebook 研究的一种 Flux 架构,用途是管理数据流,Flux 数据流周期就是这个样子:

    Views ---> (actions) ----> Dispatcher ---> (registered callback) ---> Stores -------+
    |
    | V
    +-- (Controller-Views "change" event handlers) ---- (Stores emit "change" events) --+

    先有了思想,再实现的代码,于是 reducers 就实现成了这个复杂的样子。但从某些实际场景来说,比如 op 说的 click 的情况,action 直接对应函数不是更方便吗?这种场景确实更方便,毕竟 Flux 架构环节还是挺多的挺复杂的。
    这就是它这么复杂的原因。
    至于要不要去用它,得看实际业务情况。
    开卷有益。
    尽信书不如无书。
    Chemist
        6
    Chemist  
       2023-10-22 13:23:56 +08:00 via iPhone
    当一个状态是从其他很多状态合并计算过来的时候,用 useReducer 批量更新,减少 rerender 次数
    mxT52CRuqR6o5
        7
    mxT52CRuqR6o5  
       2023-10-22 13:47:58 +08:00 via Android
    这玩意儿利于调试是要配合 devtools 用的
    Leviathann
        8
    Leviathann  
       2023-10-22 13:50:31 +08:00   1
    解决了要传十几个不同的 callback 要给子组件写十几个参数的问题
    charlie21
        9
    charlie21  
       2023-10-22 14:54:58 +08:00 via Android
    dispatcher 是一个独立于视图层的层,在这处理好之后,再把计算结果传递给视图层。这样一来,视图层会更薄(更不携带计算量)了,只负责 event handler 和渲染数据

    层本身就是答案。至于 “为什么要切出额外一层” 那么一个人只能告诉你 这可以对他而言降低心智负担,对他而言也的确如此。但对你而言未必,你不就觉得是多此一举吗?如果你没觉得它在 “降低心智负担” 那么等你遇到了就知道了

    所有的答案都是为了特定的问题应运而生的,理解答案是无助于理解答案的,理解问题是有助于理解答案的。
    bthulu
        10
    bthulu  
    OP
       2023-10-22 16:24:10 +08:00
    @Leviathann 这个你可以定义一个 object obj = {}, 把这些参数都挂载到这个 obj 上, 然后给子组件只传这个 obj 就行了
    bthulu
        11
    bthulu  
    OP
       2023-10-22 16:26:23 +08:00
    @charlie21 但是我把所有与视图无关的函数都抽到一个.js 文件里, 一样能达到你这样的效果, 还不用绕这么多弯弯.
    我只能归结为外国人的思维跟中国人就是不一样. 就跟邮件地址一样, 我们觉得从大范围到小范围很快就能锁定具体位置, 老美偏要反过来.
    XCFOX
        12
    XCFOX  
       2023-10-22 16:31:03 +08:00
    你说的对,在 2023 年 useReducer 和 Redux 可以说是最落后的状态管理方案了。

    现在有好的多的状态管理解决方案:
    喜欢 Redux 这种单向数据流思维的可以用: https://github.com/pmndrs/zustand
    喜欢 React Hook 函数式思维的可以用: https://github.com/pmndrs/jotai
    喜欢 vue3 reactive 的可以用: https://github.com/pmndrs/valtio

    早期 React 状态管理大家都是摸着石头过河,难免会走出 useReducer 和 Redux 的弯路。
    jsq2627
        13
    jsq2627  
       2023-10-22 18:36:48 +08:00 via iPhone
    我很不解为什么要把 useReducer 做到 react core 里面
    Leeeeex
        14
    Leeeeex  
    PRO
       2023-10-22 23:08:35 +08:00
    歪个楼,我想知道 webstorm 里面如何点击跳转到 dispatch 对应的 effects 里面。我们用的是 dva + umi ,dispatch 里面是 "module/effects",是个字符串,webstorm 无法识别。
    leokun
        15
    leokun  
       2023-10-23 08:59:18 +08:00
    useReducer 也可以做到类型安全,不过要在 typescript 上花一些功夫,当然这种花拳绣腿大家肯定看不上,不如试原子化的状态库,例如 https://jotai.org/https://github.com/pmndrs/zustand
    NessajCN
        16
    NessajCN  
       2023-10-23 09:00:26 +08:00
    就是 state 太多的时候给你合并用的
    realJamespond
        17
    realJamespond  
       2023-10-23 09:45:16 +08:00
    传参时巨有用,当接口有 10 个参数时你不可能写 10 个 state 吧
    yimity
        18
    yimity  
       2023-10-23 10:17:28 +08:00
    这个还是很有用的,多个状态交织起来的时候,很清晰很好用: https://yimity.com/2023/10/23/usereducer.html
    7inFen
        19
    7inFen  
       2023-10-23 10:38:52 +08:00
    因为 redux 出的早又深入人心,hook 出来后为降低使用负担,兼容了 redux 的思路。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5159 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 07:23 PVG 15:23 LAX 23:23 JFK 02:23
    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