【问题标题】:Firing off multiple API calls and updating local state in React在 React 中触发多个 API 调用并更新本地状态
【发布时间】:2021-08-09 15:12:44
【问题描述】:

我一直在使用 React 应用程序,遇到了一个奇怪的问题,我想我知道其原因,但仍然找不到解决方法。我有一个存储在变量中的对象数组。现在我需要对该数组中的每个对象进行 API 调用,并在收到调用响应时更新其上的某个字段,然后设置 React 组件的状态。

API 调用一次接收一个对象作为参数,因此我需要为状态数组中的每个对象同时进行多个 API 调用。如此多的 API 调用和大量的状态设置器函数调用。

实际的代码库非常复杂,所以我重构了它的基本版本here。 API 调用只会在现有对象上添加一个email 属性,然后更新本地状态。我已经使用setTimeout 模拟了一个 API 调用,并且 API 调用函数在组件挂载时触发。当循环结束并且所有setState 调用都完成后,我在浏览器上得到的只是状态变量中的最后一个对象,而不是所有对象。

所以我期待这样的回应

[
  {
    id: 1,
    name: 'Adam',
    email: 'adam@gmail.com'
  },
  {
    id: 2,
    name: 'Michael',
    email: 'michael@gmail.com'
  },
  {
    id: 3,
    name: 'Joseph',
    email: 'joseph@gmail.com'
  },
  {
    id: 4,
    name: 'Noah',
    email: 'noah@gmail.com'
  }
]

但我得到的却是

[
  {
    id: 4,
    name: 'Noah',
    email: 'noah@gmail.com'
  }
]

我猜这是因为 React 状态变量的 setter 函数的异步特性。所以,连续的 set state 调用都使用初始状态,因为之前的还没有更新状态。

所以,问题来了,我需要立即对数组中的所有条目进行 API 调用,一旦我得到响应,我需要更新状态。我在这里看到的一些答案谈论使用 Promise.all 但我相信这将等到所有 API 调用都得到解决,但这会影响我的应用程序的性能。也不能在这里使用 useEffect ,因为我不想等待一个 API 调用完成然后再调用下一个。但也许我没有正确理解 useEffect?

我自己真的想不出任何解决方案,因此非常感谢您帮助找出解决此问题的另一种方法。

【问题讨论】:

  • 您能否进行 API 调用并且仅在所有调用完成后才更新状态?
  • 请在您的问题中包含minimal, reproducible example(不仅在 JSFiddle 上)。
  • @CVerica 很遗憾,我不能 :( 不能等待所有 API 调用返回数据,因为随着时间的推移,数组会变得更大,并且它会真正影响应用程序的性能如何用户体验它。

标签: javascript reactjs


【解决方案1】:

您需要将users 对象作为依赖项传递给useEffect(),否则每次调用fetchUsers() 时它都会访问其初始状态。

  React.useEffect(() => {
    fetchUsers();
  }, [users]);

users 的初始状态是此处定义的空数组

const [users, setUsers] = React.useState([]);

您可以阅读文档

如果传入一个空数组([]),效果里面的props和state 总是有它们的初始值。

请阅读the docs。

【讨论】:

  • 但这只是意味着每次我更新用户时,它都会再次获取所有用户,这将获取一个用户并再次调用更新程序函数,这样最终会陷入无限循环。我只需要调用一次。
  • 是的,没错。这种设计本质上是有缺陷的。我只是指出了这样一个事实,即任何未作为依赖项传递给useEffec() 的变量每次都将使用其初始状态。您绝对不应该像在小提琴中那样每次都重新分配整个 users 对象。 Array.push() 呢?
  • Array.push 如果我可以在它之后重新渲染 React 组件,它将工作得非常好。需要使用 state setter 函数来触发重新渲染来更新 UI ☹️
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2020-05-30
  • 2017-01-24
  • 1970-01-01
相关资源
最近更新 更多