从 api 获取时反应 useEffect 无限循环

Posted

技术标签:

【中文标题】从 api 获取时反应 useEffect 无限循环【英文标题】:React useEffect Infinite loop when fetching from api 【发布时间】:2022-01-12 09:11:54 【问题描述】:

我正在尝试将我的 fetch 请求中的数据存储到一个状态中,但即使没有依赖关系,它最终也会无限循环。当我删除 div 中的代码时,我过滤掉并映射出数组,它似乎没有无限循环,但我不知道为什么过滤/映射会导致它像那样循环

function App() 
  const [searchTerm, setSearchTerm] = useState("");
  const [students, setStudents] = useState([]);
  const [isActive, setIsActive] = useState(false);
  const average = (array) => 
    return array.reduce((a, b) => a + parseFloat(b), 0) / array.length;
  ;
  useEffect(() => 
    const api = async () => 
      await fetch("https://api.hatchways.io/assessment/students")
        .then((res) => res.json())
        .then((data) => setStudents(data.students));
    ;

    api();
  , []);
  return (
    <div className='bg-gray-300 h-screen flex items-center justify-center'>
      students
        .filter((student) => 
          if (searchTerm === "") 
            return student;
           else if (
            student.firstName
              .toLowerCase()
              .includes(searchTerm.toLowerCase()) ||
            student.lastName.toLowerCase().includes(searchTerm.toLowerCase())
          ) 
            return student;
          
        )
        .map((student, i) => (
          <div
            key=i
            className='flex items-center space-x-8 px-8 py-3 border-b'>
            <div className='flex items-start w-full space-x-7'>
              <div className='border overflow-hidden rounded-full'>
                <img
                  className='w-24 h-24 bg-contain'
                  src=student?.pic
                  alt='student school portrait'
                />
              </div>
              <div className='flex flex-col justify-between space-y-4 w-full'>
                <div className='flex items-center justify-between'>
                  <h1 className='font-bold text-5xl'>
                    student?.firstName student?.lastName
                  </h1>
                  <button onClick=setIsActive(!isActive)>
                    isActive ? (
                      <AiOutlinePlus className='h-7 w-7' />
                    ) : (
                      <AiOutlineMinus className='h-7 w-7' />
                    )
                  </button>
                </div>
                <div className='pl-3'>
                  <p>Email: student?.email</p>
                  <p>Company: student?.company</p>
                  <p>Skill: student?.skill</p>
                  <p>Average: average(student?.grades).toFixed(2)%</p>
                </div>
              </div>
            </div>
          </div>
        ))
    </div>
  );

【问题讨论】:

【参考方案1】:

如果您使用async/await,则无需链接.then()。 尝试将您的 useEffect 更新为:

     useEffect(() => 
        api();
      , []);

        const api = async () => 
             let res = await fetch("https://api.hatchways.io/assessment/students");
             let data = await res.json();
             setStudents(data.students)
        ; 

另外,在按钮单击处理程序中使用箭头函数:

<button onClick=()=>setIsActive(!isActive)>

【讨论】:

刚刚尝试使用它,但仍然没有运气,由于某种原因,我在 useEffect 中使用 setStudents 时遇到了问题 导入是正确的,我也有这个,还有 useState,我的学生占位符状态是一个空数组 @StevenSmith 请尝试更新的答案,第一个代码。 我刚试了一下,还是会无限重复。当我出于某种原因在 useEffect 中设置了 setStudents 时,它不喜欢它。 @StevenSmith 将函数移到 useEffect 之外【参考方案2】:

尝试使用async-await 语法

  useEffect(() => 
    const fetchData = async () => 
      const response = await fetch(
        "https://api.hatchways.io/assessment/students"
      );
      const result = await response.json();

      console.log("res", result);
    ;

    fetchData();
  , []);

如果你想处理错误,你需要添加try catch块。

【讨论】:

我的代码已经实现了 async/await【参考方案3】:

大多数情况下,我尝试在 useEffect 内部调用函数,而在 useEffect 外部调用该函数。它对我有用,试试吧。

 useEffect(() => 
        api();
      , []);
    
        const api = async () => 
          await fetch("https://api.hatchways.io/assessment/students")
            .then((res) => res.json())
            .then((data) => setStudents(data.students));
        ;

【讨论】:

我刚试过这个,但我在 .then 链之后执行 setStudents(data) 仍然存在问题【参考方案4】:

问题是没有在点击按钮时设置箭头功能:&lt;button onClick=() =&gt; setIsActive(!isActive)&gt;

【讨论】:

【参考方案5】:

&lt;button onClick=setIsActive(!isActive)&gt;这可能是罪魁祸首。您正在更改每个 rander 中的状态。您应该将 () =&gt; setIsActive(!isActive) 作为 onClick 处理程序传递。

【讨论】:

以上是关于从 api 获取时反应 useEffect 无限循环的主要内容,如果未能解决你的问题,请参考以下文章

如何在useEffect钩子反应中停止内存泄漏

React useEffect() 无限重新渲染以获取所有尽管有依赖关系

用于获取数据的自定义反应钩子在第二次点击时未提供数据

在使用 graphql 的 useQuery 获取的数据更新 useEffect 钩子内的状态变量时防止无限渲染

面试官:如何解决React useEffect钩子带来的无限循环问题

useEffect - 更新状态时防止无限循环