35 条回复  ·  752 次点击
wang4012055 小成 2024-3-29 15:11:16
函数式编程理念是函数无副作用,所以你的调用函数最好不要引用外部状态,使用传参方式.这样使用 callback 就没什么问题了.
jinliming2 小成 2024-3-29 15:33:36
不知道你的 aHandle 和 bHandle 的具体逻辑,不过仅目前的这段代码的逻辑来说,按照我的思路,我会把 aHandle 和 bHandle 直接写成 useEffect 。
useEffect(() => {
if (type !== aaa) return;
// aHandle 的函数体,直接处理,而不是调函数
}, [type]);
useEffect(() => {
if (type !== bbb) return;
// bHandle 的函数体,如果要异步处理,就立即执行包一下
let cancel = false;
(async () => {
await xxx;
if (cancel) {
return;
}
//...
})();
return () => {
cancel = true;
};
}, [type]);
IvanLi127 小成 2024-3-29 16:08:29
按你这个需求,好像直接把那一行的 lint 禁用掉好了……
Terry166 小成 2024-3-29 16:17:25
Effect Events are not reactive and must always be omitted from dependencies of your Effect. This is what lets you put non-reactive code (where you can read the latest value of some props and state) inside of them.
参考文档:
https://react.dev/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events
w4ngzhen 小成 2024-3-29 16:42:37
```jsx
const App = () => {
    const [count, setCount] = useState(1);
    const handle = () => {
        console.log('做些事');
    }
    useEffect(() => {
        handle();
    }, [count])
    return <button onClick={() => setCount(count + 1)}>Add One</div>
}
```

感觉大家没有回答到点上啊。首先,React 中的函数式组件,每“运行”一次,是一个时刻的结果。比如上面的 App 函数,完成一次加载以后。实际上就是运行了一次 App 函数,对于第一次视为 t1 ,t1 流程是:
1. 初始化了一个 count 的 state
2. 通过变量`handle`定义了一个函数
3. 执行了一次 useEffect
4. 返回了一个`<button />`

这里面最关键的点是步骤 3 执行 useEffect 。在第一次运行的时候,这个匿名方法:

```js
// t1 时刻的匿名函数
() => {
    handle(); // t1 时刻的 handle 变量
}
```

被 React 存放到了内部,并且它捕获了 t1 时刻的变量`handle`,并且,通过`[count]`定义了依赖项。并且,t1 的匿名函数会执行一次。

当你点击按钮的时候,由于调用了 setCount ,在上述场景下,会导致 App 重新执行一次,我们把第二次执行的流程视为 t2 。它的过程是:

1. 由于第 2 次了,useState 拿到的值不再是初始值,而是上一次 set 的值,在上面的例子是 2 ;
2. 通过变量`handle`定义了一个函数。这里的 handle ,跟 t1 阶段的 handle 完全是两个变量,它们仅仅是名字一样,代码块一样而已。
3. 执行一次 useEffect 。此时,生成了一个 t2 时刻的匿名函数:

```js
// t2 匿名
() => {
    handle(); // 这里的 handle 也是 t2 时刻的 handle ,跟 t1 的 handle 没有任何关系
}
```

此时,t1 的 count = 1 与 t2 的 count = 2 不一样了,所以,useEffect 中的匿名函数( t2 版本)会执行一次,handle 自然就是 t2 版本的 handle 。

另外,上述场景中的 handle 能用 count 这个 state 吗?当然可以,因为 t2 时刻的 handle 捕获的是 t2 时刻的 count 。
wpzz 小成 2024-3-29 16:50:31
useEffect 不要这么写,如果里面代码量上来了,refs [] 会监听超级多变量和函数。

这里面函数又套了 useCallback ,维护会爆炸。
willx12123 小成 2024-3-29 17:17:33
把 lint 禁掉就行了,hooks lint 不太智能,挺烦的
neotheone2333 小成 2024-3-29 17:32:21
非常的典型的 useEvent 场景,直接用 useMemoizedFn 就行了。否则就放在 onClick 里面做
leoskey 小成 2024-3-29 17:46:51
正如前排所说你可能不需要使用 useEffect 。useEffect 不应该用于监听某个东西的变化,应该用于组件时卸载清理的工作,例如取消订阅。

官方文档专门对这种情况进行了说明 https://react.dev/learn/you-might-not-need-an-effect
otakustay 小成 2024-3-29 18:03:37
最新版本是 useEffectEvent ,以前版本是用 useRef 存它,然后再补个 useEffect 更新它
返回顶部