React-hook-踩坑2

71 阅读1分钟

useEffect死循环

举例:如果useEffect的数组参数中包含对象,就会出现死循环

 //模拟死循环
function useAxios(url,config={}){
    const [loading,setLoading] = useState(false)
    const [data,setData] = useState()
    const [error,setError] = useState()

    useEffect(()=>{
        setLoading(true)
        axios(url,config)
            .then(res => setData(res))
            .catch(e => setError(e))
            .finally(()=>setLoading(false))
    },[url,config])//config是对象,每次更新hook都会使用Object.is(preConfig,config)比较,每次肯定不一样,就会循环调用
                   //解决方法是将config结构出来,将每个需要的值类型分别传入[],如[url,page,pageSize]

    return [loading,data,error]
}

解决方法

config是对象,每次更新hook都会使用Object.is(preConfig,config)比较,每次肯定不一样,就会循环调用。

解决方法是将config结构出来,将每个需要的值类型分别传入[]

useEffect中修改useState值无效

useEffect(()=>{})[], 只有[],也就是模拟Mounted的时候才会出现这个情况,re-render就不会再执行useEffect的函数了,count相当在闭包中,不会得到更新。解决方案在下方

import React, { useEffect, useRef, useState } from "react";

/**
 * 
 * 每次打印的count都是0
 * 会出现问题
 * 
 */
function App(){
    const [count,setCount] = useState(0)
    useEffect(()=>{
        const timer = window.setInterval(()=>{
            //此处count每次都是0,不会更新
            console.log('count',count);
            setCount(count+1)
        },2000)

        return ()=>{
            window.clearInterval(timer)
        }
    },[])//只有[],也就是模拟Mounted的时候才会出现这个情况,
        //re-render就不会再执行useEffect的函数了,count相当在闭包中,不会得到更新

    return<div>count:{count}</div>
}

//解决方式一
function App2(){
    const [count,setCount] = useState(0)
    let _count = 0 
    useEffect(()=>{
        const timer = window.setInterval(()=>{
            //此处count每次都是0,不会更新
            console.log('count',_count);
            setCount(++_count)
        },2000)

        return ()=>{
            window.clearInterval(timer)
        }
    },[])

    return<div>count:{count}</div>
}


//解决方式2 推荐
function App3(){
    const [count,setCount] = useState(0)
    let _count = useRef(0)
    useEffect(()=>{
        const timer = window.setInterval(()=>{
            //此处count每次都是0,不会更新
            console.log('count',_count.current);
            setCount(++_count.current)
        },1000)

        return ()=>{
            window.clearInterval(timer)
        }
    },[])

    return<div>count:{count}</div>
}



export default App3