35 条回复  ·  504 次点击
jjwjiang 小成 2024-3-29 13:48:09
很简单,你不要在 aHandle 和 bHandle 里用 prop 和 state 就可以了,你把他们当成 sateless 的方法,需要这类状态直接通过 effect 里传进去,就不会有依赖问题了
realJamespond 小成 2024-3-29 13:49:13
用 ref 是正解,不过如果 aHandle ,bHandle 没有其他依赖项也可以正常引用,就是一直保持组件渲染第一次的地址
Radix10 小成 2024-3-29 14:32:16
这个应该不需要 hook 吧
super996 小成 2024-3-29 14:46:41
在切换 type 的那个 onChange/onSelect/onClick 做,
onChange={(type: string) => {
            if (type === 'aaa') {
              aHandle()
            } else if (type === 'bbb') {
              bHandle()
            }
            // ...
          }}
Marthemis 小成 2024-3-29 15:04:35
meta575 super996 是正解。useEffect 是处理函数的副作用,而不是去监听值(这两者在某些场景下容易混淆)
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 。
返回顶部