You need to enable JavaScript to run this app. React useEffect Hook 实现未知总页数API全量请求的最佳方案
优惠活动
大模型
产品
解决方案
定价
更多

React useEffect Hook 实现未知总页数API全量请求的最佳方案

现有代码卡死的根因
  • 缺少依赖数组的useEffect会在组件每一次重渲染时都重新执行
  • Effect内部写了同步while循环,这个循环不会等待异步fetch的返回结果,会一直占用浏览器主线程,直接造成页面卡死
  • res.json()是异步Promise,代码没有等待它的resolve结果,直接把Promise对象传给了people.concat,根本拿不到真实的人物数据
  • 状态更新直接使用了闭包捕获的旧state值,存在竞态更新的问题
核心疑问解答
  • 完全不适合在useEffect的首次执行流程里跑完全部分页请求:多页请求本身是异步串行的非阻塞流程,强行把所有请求塞进一次同步执行的effect逻辑里,既违背JS异步执行的基本特性,也会完全脱离React的状态渲染周期,必然引发死循环、内存泄漏、重复请求的问题。正确的通用范式是把单页请求拆为独立执行单元,由状态变更驱动每一次请求的发起。
  • 必须将所有影响请求逻辑的动态变量传入useEffect的依赖数组:你实现的分页逻辑本质是通过page自增推进请求进度,当接口返回404时通过gotEveryone状态终止请求。这种逻辑完全依赖「依赖值变化触发effect重跑」的内置机制,漏写依赖会直接导致请求逻辑失控,和你现在遇到的卡死问题直接相关。
可用的调整后实现
import React, { useState, useEffect } from 'react';

function GetAllPeople() {
  const [page, setPage] = useState(1)
  const [people, setPeople] = useState([]);
  const [gotEveryone, setGotEveryone] = useState(false)
  const [error, setError] = useState(null)

  useEffect(() => {
    // 已经拉完全部数据/出现错误时,直接终止当前effect逻辑,不发请求
    if (gotEveryone || error) return

    // 定义单次页请求逻辑
    const fetchPage = async () => {
      try {
        const res = await fetch(`https://swapi.dev/api/people/?page=${page}`)
        if (res.ok) {
          // 等待json解析完成,拿取真实响应数据
          const response = await res.json()
          // 用函数式更新state,避免闭包拿到旧的people值
          setPeople(prevPeople => prevPeople.concat(response.results))
          // 页码自增,触发下一次effect执行、拉取下一页
          setPage(prevPage => prevPage + 1)
        } else if (res.status === 404) {
          // 超过总页数的请求会返回404,标记全部数据拉取完成
          setGotEveryone(true)
        } else {
          setError(res.status)
        }
      } catch (e) {
        setError(e.message)
      }
    }

    fetchPage()
  }, [page, gotEveryone, error]) // 把所有影响effect执行的依赖显式声明

  return (
    <div>
      {error && <div>请求出错:{error}</div>}
      {gotEveryone && <div>全部人物数据加载完成</div>}
      <ul>
        {people.map((person, index) =>
          <li key={index}>
            {person.name}
          </li>
        )}
      </ul>
    </div>
  )
}

export default GetAllPeople;

内容的提问来源于stack exchange,提问作者C. Ball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 17:15:01