You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS中API数据返回后调用setUsers更新状态异常:循环中仅单个用户被添加至状态数组

问题原因与解决方案

这个问题我之前也碰到过,核心原因是React状态更新的异步特性加上闭包捕获的旧状态值导致的。

为什么会只保留一个用户?

你在for循环里每次调用setUsers([...users, user])时,这里的users变量捕获的是组件初始渲染时的空数组([])——因为React的状态更新不会立即改变当前作用域里的users变量,而是会在下一次渲染时更新。所以每次循环执行的都是:

setUsers([...[], user]) // 等价于 setUsers([user])

最后一次循环的user会覆盖之前的状态,所以最终users里只有最后一个用户。

两种解决方案

方案1:使用函数式更新推荐

React的setState支持传入一个函数,这个函数会接收最新的状态值作为参数,这样就能确保每次更新都是基于最新的状态:

const [users, setUsers] = useState([])
try {
  const doc = await getDocument(searchObj)
  if (doc.status === 200) {
    for (let course of doc.data.course) {
      const user = await getUser(course.document.userId)
      if (user.status === 200) {
        // 使用函数式更新,基于前一次的状态追加用户
        setUsers(prevUsers => [...prevUsers, user])
      }
    }
  }
} catch (error) {
  console.log(error)
}

方案2:先收集所有用户再一次性更新更高效

如果你的用户请求之间没有依赖关系,还可以先把所有用户数据收集到一个临时数组里,最后再一次性更新状态,这样能减少不必要的组件重渲染:

const [users, setUsers] = useState([])
try {
  const doc = await getDocument(searchObj)
  if (doc.status === 200) {
    const fetchedUsers = []
    for (let course of doc.data.course) {
      const user = await getUser(course.document.userId)
      if (user.status === 200) {
        fetchedUsers.push(user)
      }
    }
    // 一次性更新状态
    setUsers(fetchedUsers)
  }
} catch (error) {
  console.log(error)
}

如果想进一步优化,还可以用Promise.all并行请求所有用户(前提是接口支持并行调用),这样能减少等待时间:

const [users, setUsers] = useState([])
try {
  const doc = await getDocument(searchObj)
  if (doc.status === 200) {
    // 并行发起所有用户请求
    const userPromises = doc.data.course.map(course => 
      getUser(course.document.userId)
    )
    const userResponses = await Promise.all(userPromises)
    // 过滤出成功的用户数据
    const fetchedUsers = userResponses.filter(res => res.status === 200)
    setUsers(fetchedUsers)
  }
} catch (error) {
  console.log(error)
}

内容的提问来源于stack exchange,提问作者Ciprian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 20:12:49