【问题标题】:React JS useEffect hook send infinite no of request if i add an dependency如果我添加依赖项,React JS useEffect hook 将发送无限的请求
【发布时间】:2021-10-16 18:00:33
【问题描述】:

我在 Django 中创建了一个 API,用于在我的 React JS 应用程序中获取 TODO 列表任务,但是当我在 useEffect Hook 的依赖数组中使用 useState 的 allTask​​s 时,它开始发送无休止的 get 请求。如果我将依赖项数组留空然后它工作正常,我也无法理解这是如何发生的,但是如果后台有一些数据发生变化,我必须手动刷新页面。

下面是Tasklist.js组件的代码

import React,{useState, useEffect} from 'react'
import axios from 'axios'   
import Task from './Task'

function TaskList() { 
    async function getAllTasks(url){
        let resp = await axios.get(url);  
        let all_tasks= await resp.data   
        return all_tasks;
    }
    const [allTasks, setAllTasks]= useState([])
    useEffect(()=>{
        async function appendTasks(){
            let alltasks= await getAllTasks('http://127.0.0.1:8000/api/retrieve')
            setAllTasks(alltasks)
        }
        appendTasks()
    },[allTasks])
    return (
        <div className="TaskList">
            {
                allTasks.map(function(task){ 
                    return( 
                        <Task key={task.id} task={task} /> 
                    )
                })
            }
        </div>
    )
}

export default TaskList


【问题讨论】:

  • 每次标记的依赖项之一发生更改时,都会运行 useEffect 挂钩。所以在这种情况下,从依赖数组中删除 allTask​​s
  • 在依赖项中添加some data changes in background 而不是allTasks
  • 这能回答你的问题吗? Infinite loop in useEffect
  • @im_baby 不,它没有
  • @OliverIlmjärv 但是如果我从依赖数组中删除 allTask​​s 那么它不会自动更新..如果任务发生变化

标签: reactjs react-redux axios react-router react-hooks


【解决方案1】:

你得到了一个无限循环,因为你正在修改 useEffect 本身的 useEffect 依赖项。

删除你的依赖来解决你的问题:

useEffect(()=>{
    async function appendTasks(){
        let alltasks= await getAllTasks('http://127.0.0.1:8000/api/retrieve')
        setAllTasks(alltasks)
    }
    appendTasks()
},[])

删除依赖。例如,如果您想刷新数据,可以设置一个间隔以在每个时间间隔调用您的后端。

useEffect(()=>{
    async function appendTasks(){
        let alltasks= await getAllTasks('http://127.0.0.1:8000/api/retrieve')
        setAllTasks(alltasks)
    }
    const interval = setInterval(() => appendTasks(), 30000) // 30000ms = 30 secondes
    return () => clearInterval(interval);
},[])

在这里,您将每 30 秒刷新一次任务。

当然还有其他选择,具体取决于您的需要。

【讨论】:

    【解决方案2】:

    首先 - useEffect 每次其依赖项更改时都会运行,在这种情况下,它是因为您将 allTasks 指定为依赖项,并且在 useEffect 本身中您调用 setAllTasks 更改 allTasks 所以再次调用 useEffect ,所以setAllTasks 再次被调用,所以allTasks 被更改并且useEffect 被再次调用,依此类推......我希望你现在明白为什么你会得到无限数量的调用。现在的解决方案 - 在这种情况下你真的不需要 allTasks 依赖 - setAllTasks 就足够了 - 为什么?因为在useEffect 中没有任何地方使用allTasks 变量。

    解决方案:

    useEffect(()=>{
            async function appendTasks(){
                let alltasks= await getAllTasks('http://127.0.0.1:8000/api/retrieve')
                setAllTasks(alltasks)
            }
            appendTasks()
        },[setAllTasks]) // notice the change here
    

    第二个 - 与问题无关,但你应该在 useEffect 依赖数组中包含所有依赖项 - 在这种情况下,函数 getAllTasks 也应该包括在内 - 但这会再次产生无限数量的调用 - 我建议你阅读一些东西关于 useMemo 和 useCallback,但对你来说最简单的解决方案应该是这样的

    useEffect(()=> {
        async function getAllTasks(url){
          let resp = await axios.get(url);  
          let all_tasks= await resp.data   
          return all_tasks;
        }
        let response = await getAllTasks('http://127.0.0.1:8000/api/retrieve')
        setAllTasks(response)    
    }, [setAllTasks]) 
    

    【讨论】:

      【解决方案3】:

      您需要在代码中替换的是 useEffect 依赖数组
      “allTask​​s”和“addTodos”
      例如: const [addTodos, setAddTodos]= useState([])

      注意:看下面的sn-p来了解一下

      从“反应”中导入 {useState };
      从“./GetTodoList”导入GetTodoList;

      导出默认函数 AddTodo() {

      const [input, setInput]= useState("");
      const [addTodos, setAddTodos]= useState([])
      
      const setInputValue =(e)=>{
          setInput(e.target.value)
      }
      
      const addToLocalStorage=(e)=>{
          e.preventDefault();
          setAddTodos([...addTodos, {"task": input}])
          localStorage.setItem("todo", JSON.stringify(addTodos))
      }
      
      return (
          <div>
              <input value={input} onChange={setInputValue} type="text" />
              <button onClick={addToLocalStorage}>Add addTodos</button>
              <GetTodoList addTodos={addTodos}/>
          </div>
      )
      

      }

      导入 { useEffect, useState } from "react";

      函数GetTodoList({addTodos}) {

      const [todoList, setTodoList] = useState([])
      
      const getTodo=()=>{
          const result = localStorage.getItem("todo");
          setTodoList(JSON.parse(result))
          //setTotos(JSON.parse(result))
      }
      
      useEffect(() => {
          getTodo();
      }, [addTodos]) //addTodos as dependency, when the setAddTodos updates then useEffect recalls getTodo() with out hard refresh 
      return (
          <div>
            {(todoList)?
              todoList.map(todo=><p>{todo.task}</p>) : ""}
          </div>
      )
      

      }

      导出默认的GetTodoList

      【讨论】:

        猜你喜欢
        • 2020-11-10
        • 2021-02-23
        • 2020-10-26
        • 2019-10-24
        • 2019-10-25
        • 2020-03-07
        • 2020-02-25
        • 2020-06-11
        • 2020-03-30
        相关资源
        最近更新 更多