a,b,c 同时改变,这个副作用被触发了3次,怎么让它只触发1次呢?
除了防抖还有什么办法吗
useEffect(() => {
console.log(666)
}, [a, b, c])
a,b,c 同时改变,这个副作用被触发了3次,怎么让它只触发1次呢?
除了防抖还有什么办法吗
useEffect(() => {
console.log(666)
}, [a, b, c])
怎么得出来的结论。。。。看看它触发了几次
function Foo() {
const [a, setA] = useState(0);
const [b, setB] = useState(0);
useEffect(() => {
console.log(+new Date(), a, b);
}, [a, b]);
return (
<>
a:{a}, b:{b}
<button
onClick={() => {
setA(a + 1);
setB(b + 1);
}}
>
click me
</button>
</>
);
}
你得考虑你这个副作用函数是在什么情况下需要执行, 里面是不是还需要增加条件判断去保证只执行一次.
光是依靠deps, 很多时候你没法去完全避免的, 那后面要是增加依赖怎么办呢? 首先得从你这个方法本身的逻辑入手才对.
举个例子
useEffect(() => {
if (!a || !b || !c) return;
console.log(123);
}, [a, b, c])
emmm 分页器相关参数会用一个对象去包裹。如果单独变化A 就变化对象中的A 并更新这个对象。 如果批量更新 就批量更新对象中的属性。然后再更新这个对象。
const [pagination,setPagination] = useState({size:10,page:0})
// 单独更新
setPagination({...pagination,size:20})
// 批量更新
setPagination({...pagination,size:20,page:0})
// 依赖
useEffect(() => {
}, [pagination])
至于使用防抖为什么setState会有问题,set完视图不更新,还是上次的数据。一个可能的原因是因为防抖采用的是延迟开始前调用的策略。
setSize 完成后 就发请求去了。setpage应该发起的请求忽略了。可以参考lodash debounce的实现。采用延迟结束后调用。这样能保证最后一次更新的数据一定会发起一次effect。 但是不太推荐这样的做法。建议好好梳理依赖项。
react 更新机制是:收集要更新的属性,然后一次性更新,所以这个场景只会触发一次。
楼上有人说到这个,这个是不准确的。只有在原生事件的回调函数中才会这么处理,其他如setTimeout
/Promise
等情形的回调中是不会批量处理的。
React 18 改变了这个默认行为,使其在所有场景都批量更新(Batch Update)。
React 18 以下版本有个非公开 API unstable_batchedUpdates
可以强制手动批量更新。(不推荐使用,建议修改代码组织方式)
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
既然同时触发,只监听
a
不可以吗?