UseEffect无限执行

时间:2020-11-03 18:32:51

标签: reactjs use-effect

当我收到数据时,我使用useEffect钩子通过调用另一个函数getData从数据库中获取数据。

const [employees, setEmployees] = useState([])
const [shownEmployees, setShownEmployees] = useState([])
const [nbrPages, setNbrPages] = useState(0)

const getData = () => {
    axios.request(options).then((response) => {
        setEmployees(response.data)
        setShownEmployees(response.data.slice(0, nbrItems))
        response.data.length%nbrItems > 0 ? setNbrPages((response.data.length/nbrItems)+1) : setNbrPages(response.data.length/nbrItems) 
        console.log(nbrPages)
    }).catch((error) => console.log(error))
    for(let i=0;i<nbrPages;i++){
        pages_temp.push(i)
    }
    console.log(pages_temp.length)
    setPages(pages_temp)
}


useEffect(() => {
    getData()
},[])

问题nbrPages始终为0,但是当我将employees用作useEffect作为依赖项时,useEffect执行了很多次,但是这次nbrPages被bieng计算。谁能解释这种行为,我已经尝试了所有事情。本质上,我想了解为什么当我将useEffect作为依赖项时employees会无限执行,employees在什么时候发生变化,从而触发useEffect钩子。

3 个答案:

答案 0 :(得分:1)

之所以会这样,是因为您正在通过getData方法更新状态下的employees

setEmployees(response.data)

这正在更新employees,并且每次员工更新时都会调用useEffect。

更新:看来您的问题不在于useEffect。您可以调试代码,看看此时发生了什么,

response.data.length%nbrItems > 0 ? setNbrPages((response.data.length/nbrItems)+1) : setNbrPages(response.data.length/nbrItems)

您可以将此部分重写为

console.log(response.data.length);
console.log(nbrItems);
console.log(response.data.length % nbrItems);

if(response.data.length % nbrItems) {
    let temp = (response.data.length/nbrItems)+1;
    console.log('Temp:', temp); 
    setNbrPages(temp);
} else {
    console.log('Inside else block');
    let temp = response.data.length/nbrItems;
    console.log('Inside else temp:', temp);
    setNbrPages(temp);
}

然后查看控制台日志是什么,并确定您的值是否正确。

Update2::您可以使用另一个useEffect解决问题。

const [employees, setEmployees] = useState([])
const [shownEmployees, setShownEmployees] = useState([])
const [nbrPages, setNbrPages] = useState(0)

const getData = () => {
    axios.request(options).then((response) => {
        setEmployees(response.data)
        setShownEmployees(response.data.slice(0, nbrItems))
        response.data.length%nbrItems > 0 ? setNbrPages((response.data.length/nbrItems)+1) : setNbrPages(response.data.length/nbrItems) 
        console.log(nbrPages)
    }).catch((error) => console.log(error))
}


useEffect(() => {
    getData()
},[])

useEffect(() => {
    for(let i=0;i<nbrPages;i++){
        pages_temp.push(i)
    }
    console.log(pages_temp.length)
    setPages(pages_temp)
},[nbrPages]);

答案 1 :(得分:0)

应用清理功能后呈现useEffect的关键

解决方案:

const [employees, setEmployees] = useState([])
const [shownEmployees, setShownEmployees] = useState([])
const [nbrPages, setNbrPages] = useState(0)
const [mounted, setMounted] = useState(true); //Add this state helping with clean see below in useEffect
const getData = () => {
    axios.request(options).then((response) => {
        setEmployees(response.data)
        setShownEmployees(response.data.slice(0, nbrItems))
        response.data.length%nbrItems > 0 ? setNbrPages((response.data.length/nbrItems)+1) : setNbrPages(response.data.length/nbrItems) 
        console.log(nbrPages)
    }).catch((error) => console.log(error))
    for(let i=0;i<nbrPages;i++){
        pages_temp.push(i)
    }
    console.log(pages_temp.length)
    setPages(pages_temp)
}

useEffect(() => {

    if (mounted){
        getData()
    }

    return ()=>{
        setMounted(false); // Cleanup function so that  function called inside renders once

    }
},[mounted])//useEffect dependency is the state added that is **mounted** 

调试API调用技术的功能

  1. 暂时避免使用axios创建实例,直到可以追溯错误为止

  2. 暂时避免使用内部逻辑将内容保存为状态,只需console.log记录您的内容并查看发生了什么情况

  3. 一旦建立了1和2,您就知道自己处在正确的轨道上,现在您知道逻辑上存在错误,然后从那里修复

     const getData = async() => {
         const {data} = await axios.get(url)
         console.log(data)
    
         //Then if this console.log bring you back data that you want
         //now start rebuilding your logic piece by piece so that if 
         //something bugs out you know that the previous step for sure is
         //not the one cause you have validated it  
     }
    

因此,如果您可以执行此调试过程,那么您将走在正确的轨道上

答案 2 :(得分:0)

  • useEffect当提供prop / state作为参数时,其工作原理与componentDidUpdate完全相同,这意味着每次对此prop / state进行更改时,它将呈现(如果您通过employees作为依赖项,这意味着它将首先执行,并且在每次axios调用之后,该值都会更新,这意味着它将一次又一次触发useEffect。
  • 将空数组作为参数传递,其工作方式为componentDidMount,这意味着它在开始时只会被触发一次。