首页 > 技术文章 > useEffect无限调用问题

Shyno 2021-01-21 20:24 原文

1.useEfect()的基本用法

 const [test,setTest] = useState(1)
    const init=()=>{
        setTest(2)
    }
  useEffect(()=>{
      init()
      console.log('kkk',test)
  },[test])

红色'test'则是监听的数据,这里的监听数据要分为两种,1是基本数据类型,2是对象和数组

2.监听原理基本理解.

  简单来说就是当修改后的值不同于修改之前就会执行.test默认为1,setTest()之后变成了2,又会执行init(),但是再次setTest()之后,test还是2,所以只会执行2次.一次默认,一次更改之后.

 但是,当每次执行test都变化时将会无限次执行

const [test,setTest] = useState(1)
    const init=()=>{
        setTest(test+1)
    }
  useEffect(()=>{
      init()
      console.log('kkk',test)
  },[test])

test每次更改都会和上次不一样,所以他会无限执行

3.监听对象和数组

当你在useEffect中监听对象或数组的时候,它会无条件无限执行.你可以理解为引用数据类型数据在赋值时每次都生成了一个新的数据.所以必定会执行.

故,不要把数组或者对象作为监听对象.

//不能这么写
const [test,setTest] = useState({name:'小明',age:'18'}) const init=()=>{ setTest({name:'小红',age:'16'}) } useEffect(()=>{ init() console.log('kkk',test) },[test])

解决方案:

   如果我每次更改的就是对象,那我怎么监听.

   1.标记法

     同步更新一个可检测的数据,然后监听这个数据.

const [test,setTest] = useState({name:'小明',age:'18'})
    const [index,setIndex] = useState(0)
    const init=()=>{
        setTest({name:'小红',age:'16'})
        setIndex(1)
    }
  useEffect(()=>{
      init()
      console.log('kkk',test)
  },[index])

  这要求每个修改都必须要同步修改index,一次都不能少.相当于又引入了一个数据,还得自己全程盯着,流程多的时候可能会乱.不建议使用

2.加判断

假如我知道数据的走向,并且可以准确找到临界点.那我可以通过判断来掐断无限更新的流程

const [test,setTest] = useState(1)
    const init=()=>{
        setTest(test+1)
    }
  useEffect(()=>{
      if(test!==2){
        init()
        console.log('kkk',test)
      }else{

      }
  },[test])

3.对象属性监听

 通过监听对象属性来判断对象变化,同时符合监听规则,不会无限执行

const [test,setTest] = useState({name:'小明',age:'18'})
    const init=()=>{
        setTest({name:'小红',age:'16'})
    }
  useEffect(()=>{
        init()
        console.log('kkk',test)

  },[test.name])

4.函数式赋值.

useState()可以通过返回返回值的方式赋值,在这个函数中可以拿到上次更改的state值,并且阻断useState自身

 

const [test,setTest] = useState(1)
    const init=()=>{
        setTest((i)=>{
           if(i<2){
               console.log('???',i)

               return i+1
           }else{
                return i
           }
        })
    }
  useEffect(()=>{
        init()
        console.log('kkk',test)
  },[test])

 

5.结合原因从根源上避开这个问题

具体的方案可访问我的另一篇博客:hooks中,useEffect无限调用问题产生的原因

 

推荐阅读