请教一个 react hook 的问题

41 天前
 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

2582 次点击
所在节点    React
53 条回复
NessajCN
41 天前
aHandle bHandle 不会每次 render 重新生成
weixind
41 天前
使用 react-query 或者类似的东西。
Asuler
41 天前
@NessajCN 啊?
sadyx
41 天前
ahooks/useRequest 感觉可以满足你的需求
meta575
41 天前
这个场景不需要 useEffect, 如果你需要根据某个值触发对应操作, 应该是在获取到 type 的位置调用对应函数, 即便有多个位置.
10bkill1p
41 天前
react unforget
XFeng34
41 天前
meta575 说的对,你没要实现这个功能的话,可以试试 ahooks 提供的 useMemoizedFn
lisianthus
41 天前
我是这样这样处理的:每次渲染重新生成函数,然后用 ref 引用这个函数,这样的话函数就能获取到最新值,也不用把函数加到 useEffect 的依赖里,不知道有没有优雅的写法。

aHandleRef.current = () => {};

useEffect(() => {
if (type === "a") {
aHandleRef.current();
}
}, [type])
sjhhjx0122
41 天前
如果你的 type 是外部传进来的,其实你完全可以直接写不需要 useEffect
Asuler
41 天前
但是用了 useRef 的话,其实就跟 ahook 里的 useMemoizedFn 类似处理了,这样子就又回到我说的问题了: 难道只能用 useRef 或者基于 useRef+useCallback 封装的一些 hook ,把每个 aHandle 或者 bHandle 给套上吗

害,有没有更优雅的方式
Asuler
41 天前
type 是存在 state 中的一个状态,类似小程序底部 tabbar 选中高亮的一中选中状态
7anshuai
41 天前
https://react.dev/reference/react/useEffect#removing-unnecessary-function-dependencies

把 aHandle 或 bHandle 函数定义放在组件外面或者 useEffect(() => { function aHandle() {} })
sweetcola
41 天前
之前在 reactjs/rfcs 看到的 useEvent 就是用来解决这种问题的

```
function useEvent(handler) {
const handlerRef = useRef(null);
useLayoutEffect(() => {
handlerRef.current = handler;
});
return useCallback((...args) => {
const fn = handlerRef.current;
return fn(...args);
}, []);
}
```

或者直接
```
const xxx = useRef();
xxx = () => {};

...

xxx.current();
```
Asuler
41 天前
@sweetcola useEvent 其实就跟 ahook 的 useMemoizedFn 一样,但都是用在函数上的,如果涉及的函数很多,每一个都要这样套上,感觉又不太好
leroy20317
41 天前
// eslint-disable-next-line react-hooks/exhaustive-deps 😏
sweetcola
41 天前
@Asuler React 是这样的,不愿意这样做那就只能状态和函数一起外移了
HTML001
41 天前
@Asuler #10 我之前用 react 也遇到同样的问题,最后使用的 8 楼的 ref 方式(但是这样写有种不得劲的感觉,总有种在 react/vue 里面直接操作 dom 一样的违和感)
zkkz
41 天前
@leroy20317 正解,useEffect 里面拿到的函数 aHandle ,bHandle 都是最新的,不需要放到依赖项里面。
DesnLee
41 天前
具体逻辑不清楚,如果没看过建议先看看 https://zh-hans.react.dev/learn/you-might-not-need-an-effect ,有时候并不需要 useEffect
jjwjiang
41 天前
很简单,你不要在 aHandle 和 bHandle 里用 prop 和 state 就可以了,你把他们当成 sateless 的方法,需要这类状态直接通过 effect 里传进去,就不会有依赖问题了

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

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

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

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

© 2021 V2EX