请教一个 react hook 的问题

2024-03-29 10:34:07 +08:00
 Asuler

关于 react 的 useEffect ,如果我要监听一个值,并且在值变化的时候做一些函数调用

  useEffect(()=>{
    if(type === aaa){
      aHandle();
    }else if(type === bbb){
      bHandle();
    }
  }, [type])

那我就需要把 aHandle 和 bHandle 放入依赖项中,否则 eslint 或者 sonarlint 会报警告

  useEffect(()=>{
    if(type === aaa){
      aHandle();
    }else if(type === bbb){
      bHandle();
    }
  }, [type, aHandle, bHandle])

那这样岂不是每次 render ,都会重新生成新的 ahandle 和 bHandle ,每次都会触发 useEffect 吗?

我知道有 useCallback 和 useRef 可以解决函数在每次 render 都重新生成的问题,但问题是假如我在 aHandle 里去调接口,也要获取很多放在 state 中的值作为参数,那么 useCallback 还得把那些值全部放在 useCallback 的依赖项里,搞得越来越复杂了。

难道只能用 useRef 或者基于 useRef+useCallback 封装的一些 hook ,把每个 aHandle 或者 bHandle 给套上吗。

有没有更优雅一点的写法,我想要有一个 useXXXEffect,可以只监听一个 type ,在这里面获取到的其他值都是最新的,不再额外需要传入 aHandle 或者 bHandle 。

有没有这样的 hook 或者封装成这种效果的 hook

3826 次点击
所在节点    React
53 条回复
Asuler
2024-03-29 20:45:18 +08:00
@w4ngzhen eslint 或者 sonarlint 警告就是说你没把 aHandle 和 bHandle 加到依赖项里,他们的特殊之处就是里面包含了一些异步的复杂逻辑,需要每次调用时都取到外部最新的值
Asuler
2024-03-29 20:46:27 +08:00
统一回复下:eslint 和 sonarlint 不是我说禁用就能禁用的,公司私有化部署了代码扫描平台,会用这些扫描代码,作为员工绩效的一部分,我实属无奈呀,非常难受,如果是自己的项目,那我就直接不管了,害
Asuler
2024-03-29 20:47:30 +08:00
所以说,useEffect 的用法,我其实理解错了,不应该这么用对么
Asuler
2024-03-29 20:50:16 +08:00
再统一回复下:未出世的 useEvent ,useRef ,useMemoizedFn 之类的,本质上都要对那些 aHandle ,bHandle 套上,但是
1. 我需要给每个 handle 函数都给套上
2. 如果有些函数本身已经套了某种 hook 的,我难道还要再套一层?比如 useDebounceFn ,useThrottleFn ,已经套过一层了,难道要再套一层,我感觉不太优雅了
rocmax
2024-03-29 20:51:30 +08:00
是不是把 vue 里用 watch 的习惯带来了?
type 在哪里变的就在哪里挂处理函数,useeffect 不是干这个的
lee88688
2024-03-29 22:44:45 +08:00
闭包问题,在 react 里面没有太好的解决方案,op 说的是否还要再往上套的问题是肯定的,如果想要保持引用稳定就是要付出这个代价,这也就是 react 目前的问题。
vue 或者 solidjs 这些没有这个问题是因为他们所有的数据外面都有一层壳,vue 的 val.value ,solidjs 的 value(),都是帮你在外面加了一层,当然渲染机制也不同,所以加壳就加吧。
zbowen66
2024-03-30 11:52:56 +08:00
@rocmax #45 别洗了,缺点就是缺点
dudubaba
2024-03-30 16:07:15 +08:00
这种感觉就是 eslint 的锅, 这种场景还是很多的,因为 useEffect 不能直接用 async ,所以函数定义在 useEffect 里又不能共用,抽出来又出现你这种依赖报错问题,但是实际上不加函数依赖是正常的,用这种依赖问题又一大堆冗余代码。如果全局 eslint 改不掉建议用 eslint-disable-next-line 这种禁用掉。
rocmax
2024-03-30 16:45:34 +08:00
@zbowen66 vue boy 这就破防了?
vue 里面不是一样不推荐滥用 watch 吗?到处 watch 的屎山我是见过的,哪里改变状态在哪里处理 state 不很正常吗?
react 手动依赖收集是比较麻烦,但这跟不该用 useeffect 监听状态修改有一毛钱关系吗?
zbowen66
2024-03-30 23:23:54 +08:00
@rocmax #49 哈哈,说点 react 的缺点就被喷是 vue boy ,祝你生活愉快😁,告辞
jjwjiang
2024-04-01 16:56:03 +08:00
@w4ngzhen 确实是这样,但是如果在 function 里有闭包那就是另一回事了。所以我觉得 eslint 这规则大部分时候是没用的,这规则最终导致的结果就是需要 memo 一大堆东西
HTML001
2024-04-03 17:24:34 +08:00
四天过去了,OP 最终选择什么方案?
Asuler
2024-04-04 09:08:28 +08:00
@HTML001 hook 往上套呗,代码都写了那么多了,不可能重构的,只要没出线上问题就不重构

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

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

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

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

© 2021 V2EX