哈喽,大家好呀,我是前端理想哥,今天我们来聊聊useEffect
判断依赖项变化的方式。
好多人在刚开始使用 Hooks 时,应该都遇到过图中这样的bug,
function A() {
const b = [{ text: 'hooks'}];
useEffect(() => {
console.log('b changed.');
}, [b]);
}
大家可以看到,图中代码定义了一个值为b的数组,然后把b作为了useEffect的依赖项,本意是希望b发生改变后,会触发useEffect的回调函数,若b没有改变,则回调函数不执行。但是,当你实际运行代码时,会发现每次回调函数都会执行,这是为什么呢?
要说明白这个问题,我们可以来看看 useEffect 的源码,这张图是useEffect源码中每次用来比较依赖项是否变化的方法,
function areHookInputsEqual(nextDeps, prevDeps) {
if (prevDeps === null) {
return false;
}
for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
if (Object.is(nextDeps[i], prevDeps[i])) {
continue;
}
return false;
}
return true;
}
大家可以看到,是使用了 Object.is
方法来比较的,而 Object.is
的源码又是怎么去比较的呢?大家可以继续看这张图,Object.is
的源码
module.exports = function is(a, b) {
if (a === 0 && b === 0) {
return 1 / a === 1 / b;
}
if (a === b) {
return true;
}
if (numberIsNaN(a) && numberIsNaN(b)) {
return true;
}
return false;
};
大家可以看到,Object.is
是使用了 全等 === 来比较的,这样其实就能说明问题了。为什么上面代码中每次回调函数都会执行呢?因为useEffect的依赖项是使用了 === 全等符号来进行判断的,如果依赖项是数组或者对象,即使值没有变化,引用地址也会变化,所以每次判断的结果都不一样,就会每次都会调用回调函数了。
以上,就是useEffect判断依赖项变化的方式了。
如果你觉得对自己有帮助,欢迎给理想哥一个关注,也可以私聊理想哥加入前端岗位内推群,我们会经常在群里发布各大公司急招岗位和面试求职经验,帮助大家尽快的找到工作。