skip to Main Content

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?

2

Answers


  1. 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:

    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();

    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.

    Login or Signup to reply.
  2. 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)
    }
    

    Hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search