Search code examples
javascriptreactjsnext.jstimer

How to get the current time in minutes from Timer component?


I'm using react-timer-hook library for showing the timer in my Next.js application. The timer is working fine, but the issue is I'm not able to get the current elapsed time in minutes on the handle form event. I want to send the total_time_taken in minutes.

This is the Timer component:

import { Typography } from '@mui/material';
import { useTimer } from 'react-timer-hook';

export default function Timer({ expiryTimestamp, functionCall }) {
    const {
        seconds,
        minutes,
        hours,
    } = useTimer({
        expiryTimestamp,
        onExpire: () => functionCall()
    });
    return (
        <Typography variant='h5' fontWeight={'bold'} component={'div'}>
            <span>{hours < 10 ? '0' + hours : hours}</span>:<span>{minutes < 10 ? '0' + minutes : minutes}</span>:<span>{seconds < 10 ? '0' + seconds : seconds}</span>
        </Typography>
    );
}

This is where I'm using the Timer component:

const time = new Date();
time.setSeconds(time.getSeconds() + 3600);
<Timer functionCall={handleForm} expiryTimestamp={time} />

This is the handleForm event in which I want the elapsed time in minutes in the total_time_taken object:

async function handleForm() {
        const token = Cookies.get('token');
        const formData =
        {
            user_id: userId,
            test_id: test_id,
            total_time_taken: 35,
            answers: answers
        }
        const data = JSON.stringify(formData);
        const resp = await axios.post(`answers`, data, {
            headers: {
                Authorization: `Bearer ${token}`
            }

        });
        if (resp.data.success) {
            router.push('/user/feedback/' + test_id);
        }
    }

Solution

  • It seems you are trying to access the state of the child component Timer from the parent component. This appears to be a clear case where the parent component should hold the timer state and pass the time down to the Timer component for display, and the parent component can easily reference the state it owns.

    Example:

    Timer

    function Timer({ seconds, minutes, hours }) {
      return (
        <Typography variant="h5" fontWeight={"bold"} component={"div"}>
          <span>{String(hours).padStart(2, "0")}</span>:
          <span>{String(minutes).padStart(2, "0")}</span>:
          <span>{String(seconds).padStart(2, "0")}</span>
        </Typography>
      );
    }
    

    Parent component

    const expiryTimestamp = new Date();
    expiryTimestamp.setSeconds(expiryTimestamp.getSeconds() + 3600);
    
    function App() {
      const handleForm = () => {
        const elapsed = 3600 - (hours * 3600 + minutes * 60 + seconds);
        const total_time_taken = {
          hours: Math.floor(elapsed / 3600),
          minutes: Math.floor((elapsed % 3600) / 60),
          seconds: ((elapsed % 3600) % 60) % 60
        };
    
        console.log("handleForm", {
          ...total_time_taken
        });
    
        ...
      };
    
      const { seconds, minutes, hours } = useTimer({
        expiryTimestamp,
        onExpire: handleForm
      });
    
      ...
    
      return (
        <div className="App">
          ...
          <Timer {...{ seconds, minutes, hours }} />
    
          <button type="button" onClick={handleForm}>
            Yes
          </button>
        </div>
      );
    }
    

    Edit how-to-get-the-current-time-in-minutes-from-timer-component

    enter image description here