如何理解useEffect的依赖项为引用?

本文详细讲解了在React中使用useEffect时遇到引用类型依赖引发的死循环问题,介绍了useCallback和useMemo这两个hook的作用,以及如何通过它们来正确处理函数依赖,避免副作用函数无限循环。
摘要由CSDN通过智能技术生成

useEffect这个hooks应该是我们平常在写react项目中使用频率最高的hooks之一了,它可以在依赖项改变时执行副作用函数,这是它最主要的功能。

1.当没有依赖项时,useEffect中的副作用函数只会执行一次。

const fn=()=>{}

useEffect(()=>{
    fn();
},[count])

2.当有依赖项时,如果点击一次按钮,fn就会被调用一次,useEffect会对比前后两次的count,因为count我们定义的是基本类型,所以就是判断值相不相等。

const [count,setCount] = useState(0);

const fn=()=>{}

useEffect(()=>{
    fn();
},[count])

return(
<>
   <button onClick={()=>setCount(count+1)>
    click
    </button>
</>)

3.当useEffect的依赖是引用类型的时候。我们这里把依赖项换成fn这个函数,如果我们此时运行项目,会发现控制台会一直输出1。

const [count,setCount] = useCount(0);
const fn=()=>{};

useEffect(()=>{
    console.log(1);
    setCount(count+1);
},[fn]);

原因:

1.代码运行进useEffect中,依赖为fn,调用了setCount(),数据改变导致页面重新渲染, 

2.代码从上到下执行,fn被重新定义了一遍,此时的fn不再是一开始的fn,所以第一次的fn和第二次的fn不是同一个fn,useEffect中的副作用函数被再次调用

3.setCount的再次调用,又改变了state,走第2步,所以造成了死循环。

如何解决?

想要知道如何解决这个问题,应该先要知道useEffect对比两次依赖的时候是如何对比的,通过翻阅资料,找到了对比依赖时,调用的是Object.is()方法,Object.is(a,b),如果a,b是基本数据类型,直接对比二者的值,不相等则返回false,或者返回true,这里是不会进行数据类型转换比较的。

如果a,b是引用数据类型,直接判断二者的地址是否相同,不相同则返回FALSE,否则返回true。 

如果就是有需求,当fn改变时,去做一些操作,那么我们该如何处理这种情况呢?

解决办法

使用useCallback这个hook,useCallback是当某个依赖改变时,返回一个函数,在依赖没有改变时,useCallback会缓存第一次返回的函数。

const [count,setCount] = useCount(0);
const fn= useCallback(()=>{
    const callFn = ()=>{
        //to do
    }
    return callFn;
},[]);

useEffect(()=>{
    console.log(1);
    setCount(count+1);
},[fn]);

效果图:这样就不会出现死循环了。

 如果我们需要依赖是一个对象呢?

那么我们需要使用的是useMemo这个hook,这个hook是帮助我们缓存一个数据的,useCallback是帮助我们缓存一个函数的。

const [count,setCount] = useCount(0);
const objDep= useMemo(()=>{
    const obj = {name:"joker"};
    return obj;
},[]);

useEffect(()=>{
    console.log(1);
    setCount(count+1);
},[objDep]);

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值