【问题标题】:Spread Operator not copying results in React传播运算符未在 React 中复制结果
【发布时间】:2020-08-16 01:46:41
【问题描述】:

我正在尝试在 for 循环中更新 setState,但由于某种原因,状态没有被复制,它只是被替换。应该有 2 个客户,而不是我得到一个。谁能告诉我为什么会这样? console.log 正在返回两个客户端。

const handleViewClients = () => {
    for (let i = 0; i < clients.length; i++) {
      console.log(clients[i].clientid);
      fetch("http://localhost:3005/all-clients/" + clients[i].clientid)
        .then((response) => response.json())
        .then((result) => {
          console.log(result);
          setBarbersClient({
            ...barbersClient,
            client: result,
          });
        });
    }
  };

我也试过这个...console.log 正在返回我需要的内容

 Promise.all(
      clients.map((client) =>
        fetch("http://localhost:3005/all-clients/" + client.clientid)
      )
    )
      .then((resp) => resp.json())
      .then((result) => {
        console.log(result.username)
        setBarbersClient({
          ...barbersClient,
          client: result,
        });
        
      });

这是来自服务器端的路由

app.get("/all-clients/:clientid", (req, res) => {
  db.NewClientsx.findOne({
    where: {
      id: req.params.clientid,
    },
  }).then((response) => {
    res.json(response);
  });
});

【问题讨论】:

  • 2 client 你所在的州?
  • 如果我 console.log result.username 这是客户端的键,它将两个客户端都返回到控制台。但是由于某种原因,在我设置为只有一个状态之后,@bertdida
  • 您能否在问题中包含/all-clients 回复?
  • 是的,它现在就在那里@bertdida
  • 我在response 上的意思是实际的json 数据——当您console.log(result) 时您将看到的数据,您可以包含这些数据吗?

标签: reactjs for-loop react-hooks setstate


【解决方案1】:

这里没有考虑同步与异步代码的一些基本概念。状态改变(和获取)是异步的,所以它不会运行,直到这个同步循环完成执行(在此期间状态值将保持不变)。此外,出于这个原因和其他原因,在循环中更改状态是一个坏主意。

获取所有客户端,然后在最后使用获取的数据进行一次状态更改all。您可以利用 Promise.allPromise.spread 之类的东西来实现这一点。这是一个执行多次获取然后在一批中处理结果的示例:How can I fetch an array of URLs with Promise.all?

【讨论】:

  • 我在顶部使用 promise.all 添加了更新的代码,但仍然遇到同样的问题。只返回一个客户。感谢 @Jayce444 上关于异步和同步的小课
  • @Jayg713 Promise.all 返回结果数组,因此您不应该在该数组上调用 resp.json()。在添加每个新步骤之前,打印出.then 中的每个步骤。从Promise.all(...).then(res =&gt; console.log(res)) 开始,然后从那里开始
  • 我确实需要调用 resp.json() 否则它会返回一个带有标题和状态代码的非 json 数组,而不是我需要的信息。当我 console.log result.username 它返回两个客户端时,但是当它设置为状态时,只有一个客户端存在。我什至尝试在 redux 中设置它,同样的问题@Jayce444
【解决方案2】:

你犯了两个明显的错误,其中任何一个都足以导致你看到的行为。

1。您正在覆盖 client 属性。

每次调用 setter 函数时,都会覆盖 client 属性的先前值。您需要一些支持多个值的数据结构,例如地图:

setBarbersClient({
  ...barbersClient,
  clients: {
    ...barbersClient.clients,
    [result.id]: result
  },
});

您需要稍微更改渲染逻辑以适应新的数据结构。

2。您使用的是过时的参考。

当您访问 barbersClient 时,它的 setter 可能已经被调用了一个不同的值,并且您对它的引用仍然是指上一次运行渲染函数的值。您可以使用设置状态操作回调来确保您的引用是最新的。

setBarbersClient(previousValue => {
  ...previousValue,
  clients: {
    ...previousValue.clients,
    [result.id]: result
  },
});

previousValue 在设置状态动作函数体内永远不会过时。

【讨论】:

    猜你喜欢
    • 2012-02-28
    • 2020-11-12
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 2017-01-17
    相关资源
    最近更新 更多