英文:
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) => {
setTimeout(() => {
const apiResponse = [
{
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,
},
];
resolve(apiResponse);
}, 2000);
});
}
async function fetchData() {
const response = await simulateAPICall();
const totalStopTime = response.reduce(
(acc, curr) => acc + parseInt(curr.stopTime),
0
);
console.log('Total Stop Time:', 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.
答案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 'react';
const timerData = [
{
"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
}
]
const Example = () => {
const [stopTime, setStopTime] = useState()
useEffect(()=>{
const fetchStopTime = async () => {
const response = await new Promise(resolve => setTimeout(resolve, 1000, timerData));
setStopTime(response)
}
fetchStopTime()
}, [])
const totalStopTime = useMemo(()=>{
if(stopTime === undefined) return 0
return (
stopTime.reduce(
(acc, curr) => acc + parseInt(curr.stopTime),
0
)
)
}, [stopTime])
return (
<div>
{totalStopTime}
</div>
)
}
export default Example
If you use fetch
then you can replace the fetchStopTime
function with
const fetchStopTime = async () => {
const response = await fetch('some_api_url')
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 = [
{
"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
}
]
const Example = ({title}) => {
const [stopTime, setStopTime] = useState()
useEffect(()=>{
const fetchStopTime = () => {
new Promise(resolve => setTimeout(resolve, 1000, timerData))
.then(response => setStopTime(response))
}
fetchStopTime()
}, [])
const totalStopTime = useMemo(()=>{
if(stopTime === undefined) return 0
return (
stopTime.reduce(
(acc, curr) => acc + parseInt(curr.stopTime),
0
)
)
}, [stopTime])
return (
<div>
total stop time: {totalStopTime}
</div>
)
};
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Example title="Example using Hooks:" />
);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>
<!-- end snippet -->
Hope this helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论