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

2023-10-22 10:17:25 +08:00
 bthulu

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

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

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

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

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

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

2574 次点击
所在节点    React
19 条回复
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
2023-10-22 10:46:44 +08:00
这玩意除了给自己添堵真没啥用, 用起来麻烦, 找起来麻烦
easychen
2023-10-22 11:16:41 +08:00
这个本来就是可选的啊,场景简单的话直接上 mobx 之类就可以了吧。
paradox8599
2023-10-22 11:38:23 +08:00
https://github.com/pmndrs/zustand
最近在用这个,感觉更舒服一点
chaxus
2023-10-22 12:08:04 +08:00
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 架构环节还是挺多的挺复杂的。
这就是它这么复杂的原因。
至于要不要去用它,得看实际业务情况。
开卷有益。
尽信书不如无书。
kyuuseiryuu
2023-10-22 13:23:56 +08:00
当一个状态是从其他很多状态合并计算过来的时候,用 useReducer 批量更新,减少 rerender 次数
mxT52CRuqR6o5
2023-10-22 13:47:58 +08:00
这玩意儿利于调试是要配合 devtools 用的
Leviathann
2023-10-22 13:50:31 +08:00
解决了要传十几个不同的 callback 要给子组件写十几个参数的问题
charlie21
2023-10-22 14:54:58 +08:00
dispatcher 是一个独立于视图层的层,在这处理好之后,再把计算结果传递给视图层。这样一来,视图层会更薄(更不携带计算量)了,只负责 event handler 和渲染数据

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

所有的答案都是为了特定的问题应运而生的,理解答案是无助于理解答案的,理解问题是有助于理解答案的。
bthulu
2023-10-22 16:24:10 +08:00
@Leviathann 这个你可以定义一个 object obj = {}, 把这些参数都挂载到这个 obj 上, 然后给子组件只传这个 obj 就行了
bthulu
2023-10-22 16:26:23 +08:00
@charlie21 但是我把所有与视图无关的函数都抽到一个.js 文件里, 一样能达到你这样的效果, 还不用绕这么多弯弯.
我只能归结为外国人的思维跟中国人就是不一样. 就跟邮件地址一样, 我们觉得从大范围到小范围很快就能锁定具体位置, 老美偏要反过来.
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
2023-10-22 18:36:48 +08:00
我很不解为什么要把 useReducer 做到 react core 里面
chanChristin
2023-10-22 23:08:35 +08:00
歪个楼,我想知道 webstorm 里面如何点击跳转到 dispatch 对应的 effects 里面。我们用的是 dva + umi ,dispatch 里面是 "module/effects",是个字符串,webstorm 无法识别。
leokun
2023-10-23 08:59:18 +08:00
useReducer 也可以做到类型安全,不过要在 typescript 上花一些功夫,当然这种花拳绣腿大家肯定看不上,不如试原子化的状态库,例如 https://jotai.org/https://github.com/pmndrs/zustand
NessajCN
2023-10-23 09:00:26 +08:00
就是 state 太多的时候给你合并用的
realJamespond
2023-10-23 09:45:16 +08:00
传参时巨有用,当接口有 10 个参数时你不可能写 10 个 state 吧
yimity
2023-10-23 10:17:28 +08:00
这个还是很有用的,多个状态交织起来的时候,很清晰很好用: https://yimity.com/2023/10/23/usereducer.html
7inFen
2023-10-23 10:38:52 +08:00
因为 redux 出的早又深入人心,hook 出来后为降低使用负担,兼容了 redux 的思路。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/984187

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX