React中对象数组求和的问题

huangapple go评论59阅读模式
英文:

Problems with sum of objects in array with React

问题

我想计算该对象中“stopTime”的总和。

我遇到了一些解决问题的困难,我已经广泛搜索但没有成功。
我的API响应如下:

[
    {
        "id": 1,
        "stopCause": "Stop Cause 1",
        "stopTime": 3,
        "stopOperator": "Somebody",
        "createdAt": "2023-06-26T10:29:31.000Z",
        "updatedAt": "2023-06-26T10:29:31.000Z",
        "OrderId": 1
    },
    {
        "id": 2,
        "stopCause": "Stop Cause 3",
        "stopTime": 5,
        "stopOperator": "Somebody",
        "createdAt": "2023-06-26T10:29:37.000Z",
        "updatedAt": "2023-06-26T10:29:37.000Z",
        "OrderId": 1
    },
    {
        "id": 3,
        "stopCause": "Stop Cause 4",
        "stopTime": 12,
        "stopOperator": "Username",
        "createdAt": "2023-06-28T06:45:24.000Z",
        "updatedAt": "2023-06-28T06:45:24.000Z",
        "OrderId": 1
    }
]

这是计算“stopTime”总和的代码:

const totalStopTime = stopTime.reduce(
    (acc, curr) => acc + parseInt(curr.stopTime),
    0
  );

如果没有API调用的延迟,这一切都会很顺利……这总是解决为0,因为API比页面加载慢……

有没有办法解决这个问题?

英文:

I want to calculate the total sum of "stopTime" in this object.

I have some problems resolving this, I have searched far and wide without any success.
My API response looks like this:

[
    {
        "id": 1,
        "stopCause": "Stop Cause 1",
        "stopTime": 3,
        "stopOperator": "Somebody",
        "createdAt": "2023-06-26T10:29:31.000Z",
        "updatedAt": "2023-06-26T10:29:31.000Z",
        "OrderId": 1
    },
    {
        "id": 2,
        "stopCause": "Stop Cause 3",
        "stopTime": 5,
        "stopOperator": "Somebody",
        "createdAt": "2023-06-26T10:29:37.000Z",
        "updatedAt": "2023-06-26T10:29:37.000Z",
        "OrderId": 1
    },
    {
        "id": 3,
        "stopCause": "Stop Cause 4",
        "stopTime": 12,
        "stopOperator": "Username",
        "createdAt": "2023-06-28T06:45:24.000Z",
        "updatedAt": "2023-06-28T06:45:24.000Z",
        "OrderId": 1
    }
]

and here is the code to sum up "stopTime" :

const totalStopTime = stopTime.reduce(
    (acc, curr) => acc + parseInt(curr.stopTime),
    0
  );

This would all work fine and dandy if there wasn't any delay from the API call... It always resolves into 0, because the API is slower than the page loading...

Is there any way to get around this?

答案1

得分: 2

处理API响应时,应使用async/await来解决异步响应引起的问题。您需要将您的代码结构更改为以下方式:

function simulateAPICall() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const apiResponse = [
        {
          id: 1,
          stopCause: '停止原因 1',
          stopTime: 3,
          stopOperator: '某人',
          createdAt: '2023-06-26T10:29:31.000Z',
          updatedAt: '2023-06-26T10:29:31.000Z',
          OrderId: 1,
        },
        {
          id: 2,
          stopCause: '停止原因 3',
          stopTime: 5,
          stopOperator: '某人',
          createdAt: '2023-06-26T10:29:37.000Z',
          updatedAt: '2023-06-26T10:29:37.000Z',
          OrderId: 1,
        },
        {
          id: 3,
          stopCause: '停止原因 4',
          stopTime: 12,
          stopOperator: '用户名',
          createdAt: '2023-06-28T06:45:24.000Z',
          updatedAt: '2023-06-28T06:45:24.000Z',
          OrderId: 1,
        },
      ];
      resolve(apiResponse);
    }, 2000); 
  });
}

async function fetchData() {
  const response = await simulateAPICall();

  const totalStopTime = response.reduce(
    (acc, curr) => acc + parseInt(curr.stopTime),
    0
  );

  console.log('总停机时间:', totalStopTime);
}

fetchData();

simulateAPICall() 函数的调用应该由实际的API调用替代。

基本上,由于在API调用之前有 await 关键字,控制权会等待分配完成后再继续,使其看起来像同步一样。请注意,await 只能在 async 函数内部使用。

更多信息,请参阅这里这里

英文:

When dealing with API responses you should use async/await to resolve issues due to such asynchronous responses. You need to change your code structure to something like this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function simulateAPICall() {
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      const apiResponse = [
        {
          id: 1,
          stopCause: &#39;Stop Cause 1&#39;,
          stopTime: 3,
          stopOperator: &#39;Somebody&#39;,
          createdAt: &#39;2023-06-26T10:29:31.000Z&#39;,
          updatedAt: &#39;2023-06-26T10:29:31.000Z&#39;,
          OrderId: 1,
        },
        {
          id: 2,
          stopCause: &#39;Stop Cause 3&#39;,
          stopTime: 5,
          stopOperator: &#39;Somebody&#39;,
          createdAt: &#39;2023-06-26T10:29:37.000Z&#39;,
          updatedAt: &#39;2023-06-26T10:29:37.000Z&#39;,
          OrderId: 1,
        },
        {
          id: 3,
          stopCause: &#39;Stop Cause 4&#39;,
          stopTime: 12,
          stopOperator: &#39;Username&#39;,
          createdAt: &#39;2023-06-28T06:45:24.000Z&#39;,
          updatedAt: &#39;2023-06-28T06:45:24.000Z&#39;,
          OrderId: 1,
        },
      ];
      resolve(apiResponse);
    }, 2000); 
  });
}

async function fetchData() {

  const response = await simulateAPICall();

  const totalStopTime = response.reduce(
    (acc, curr) =&gt; acc + parseInt(curr.stopTime),
    0
  );

  console.log(&#39;Total Stop Time:&#39;, totalStopTime);
}

fetchData();

<!-- end snippet -->

The call to simulateAPICall() function should be replaced by the actual API call.

Basically, due to the await keyword before api call, the control waits for the assignment before moving forward making that part synchronous-like.
Note that await can only be used inside an async function.

Read more about this here or here.

答案2

得分: 0

你没有分享你的fetch调用,但一般来说,在React中不能等待异步调用。你需要使用useEffect进行一点小的技巧,以使用useState填充一些状态。然后可以使用该状态触发useMemo以有条件地计算某些操作(即Array.reduce())。

如果你使用fetch,可以将fetchStopTime函数替换为:

const fetchStopTime = async () => {
   const response =  await fetch('some_api_url')
   const data = await response.json()
   setStopTime(data)
}

这是一个代码片段,必须对代码进行修改,因为堆栈溢出的代码片段库不支持异步函数。上面的代码遵循开发人员熟悉的约定。

希望这能帮到你!

英文:

You haven't shared your fetch call but in general you can't await for an asynchronous call in React. You need to do a little bit of a hack with useEffect to populate some state with useState. You can then use the state to trigger a useMemo to conditionally calculate some operation (i.e., Array.reduce())

import { useMemo, useState, useEffect } from &#39;react&#39;;
const timerData = [
    {
        &quot;id&quot;: 1,
        &quot;stopCause&quot;: &quot;Stop Cause 1&quot;,
        &quot;stopTime&quot;: 3,
        &quot;stopOperator&quot;: &quot;Somebody&quot;,
        &quot;createdAt&quot;: &quot;2023-06-26T10:29:31.000Z&quot;,
        &quot;updatedAt&quot;: &quot;2023-06-26T10:29:31.000Z&quot;,
        &quot;OrderId&quot;: 1
    },
    {
        &quot;id&quot;: 2,
        &quot;stopCause&quot;: &quot;Stop Cause 3&quot;,
        &quot;stopTime&quot;: 5,
        &quot;stopOperator&quot;: &quot;Somebody&quot;,
        &quot;createdAt&quot;: &quot;2023-06-26T10:29:37.000Z&quot;,
        &quot;updatedAt&quot;: &quot;2023-06-26T10:29:37.000Z&quot;,
        &quot;OrderId&quot;: 1
    },
    {
        &quot;id&quot;: 3,
        &quot;stopCause&quot;: &quot;Stop Cause 4&quot;,
        &quot;stopTime&quot;: 12,
        &quot;stopOperator&quot;: &quot;Username&quot;,
        &quot;createdAt&quot;: &quot;2023-06-28T06:45:24.000Z&quot;,
        &quot;updatedAt&quot;: &quot;2023-06-28T06:45:24.000Z&quot;,
        &quot;OrderId&quot;: 1
    }
]
const Example = () =&gt; {
	const [stopTime, setStopTime] = useState()
	useEffect(()=&gt;{
		const fetchStopTime = async () =&gt; {
			const response =  await new Promise(resolve =&gt; setTimeout(resolve, 1000, timerData));
			setStopTime(response)
		}
		fetchStopTime()
	}, [])

	
	const totalStopTime = useMemo(()=&gt;{
		if(stopTime === undefined) return 0
		return (
			stopTime.reduce(
				(acc, curr) =&gt; acc + parseInt(curr.stopTime),
				0
			  )
		)
	}, [stopTime])

	return (
		&lt;div&gt;
			{totalStopTime}
		&lt;/div&gt;
	)
}

export default Example

If you use fetch then you can replace the fetchStopTime function with

const fetchStopTime = async () =&gt; {
   const response =  await fetch(&#39;some_api_url&#39;)
   const data = await response.json()
   setStopTime(data)
}

Here's an snippet where the code had to be modified because stack overflow snippet library ES2015 doesn't support async functions. The code above follows conventions developers are familiar with

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const {useState, useEffect, useMemo} = React;
const timerData = [
{
&quot;id&quot;: 1,
&quot;stopCause&quot;: &quot;Stop Cause 1&quot;,
&quot;stopTime&quot;: 3,
&quot;stopOperator&quot;: &quot;Somebody&quot;,
&quot;createdAt&quot;: &quot;2023-06-26T10:29:31.000Z&quot;,
&quot;updatedAt&quot;: &quot;2023-06-26T10:29:31.000Z&quot;,
&quot;OrderId&quot;: 1
},
{
&quot;id&quot;: 2,
&quot;stopCause&quot;: &quot;Stop Cause 3&quot;,
&quot;stopTime&quot;: 5,
&quot;stopOperator&quot;: &quot;Somebody&quot;,
&quot;createdAt&quot;: &quot;2023-06-26T10:29:37.000Z&quot;,
&quot;updatedAt&quot;: &quot;2023-06-26T10:29:37.000Z&quot;,
&quot;OrderId&quot;: 1
},
{
&quot;id&quot;: 3,
&quot;stopCause&quot;: &quot;Stop Cause 4&quot;,
&quot;stopTime&quot;: 12,
&quot;stopOperator&quot;: &quot;Username&quot;,
&quot;createdAt&quot;: &quot;2023-06-28T06:45:24.000Z&quot;,
&quot;updatedAt&quot;: &quot;2023-06-28T06:45:24.000Z&quot;,
&quot;OrderId&quot;: 1
}
]
const Example = ({title}) =&gt; {
const [stopTime, setStopTime] = useState()
useEffect(()=&gt;{
const fetchStopTime = () =&gt; {
new Promise(resolve =&gt; setTimeout(resolve, 1000, timerData))
.then(response =&gt; setStopTime(response))			
}
fetchStopTime()
}, [])
const totalStopTime = useMemo(()=&gt;{
if(stopTime === undefined) return 0
return (
stopTime.reduce(
(acc, curr) =&gt; acc + parseInt(curr.stopTime),
0
)
)
}, [stopTime])
return (
&lt;div&gt;
total stop time: {totalStopTime}
&lt;/div&gt;
)
};
// Render it
ReactDOM.createRoot(
document.getElementById(&quot;root&quot;)
).render(
&lt;Example title=&quot;Example using Hooks:&quot; /&gt;
);

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

Hope this helps!

huangapple
  • 本文由 发表于 2023年6月30日 02:23:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583716.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定