1

I'm creating a component to track the time that takes to do a task. And I'm using react-compound-timer to do that.

The problem I'm having is that I am unable to update the component state when clicking the 'stop' button.

This is the code:

import React, { useState } from 'react';
import Timer from 'react-compound-timer'
import clock from '../../../assets/images/clock-regular.svg'
import playIcon from '../../../assets/images/play.svg';
import pauseIcon from '../../../assets/images/pause.svg';
import stopIcon from '../../../assets/images/stop.svg';
import resetIcon from '../../../assets/images/reset.svg';

const LogTimer = () => {
  const [timerValue, setTimerValue] = useState(null);

  return (
    <Timer
      formatValue={(value) => `${(value < 10 ? `0${value}` : value)}`}
      initialTime={0}
      startImmediately={false}
      onStart={() => console.log('onStart')}
      onPause={() => console.log('onPause')}
      onStop={(value) => {
        setTimerValue(value);
        console.log('onStop')
      }}
      onReset={() => console.log('onReset')}
>
    {({ start, pause, stop, reset, getTime }) => 
      ( 
        <>
          <div className="d-flex align-items-center justify-content-between">
            <div className="d-flex align-items-center">
              <img src={clock} alt="clock" className="pr-2" style={{ width: '1.75rem' }}/><Timer.Hours />:<Timer.Minutes />:<Timer.Seconds /> 
            </div>
          </div>
          <div className="d-flex justify-content-between" style={{ minWidth: '9rem' }}>
            <img src={playIcon} className="control-btn" alt='play' role='button' onClick={start}></img>
            <img src={pauseIcon} className="control-btn" alt='pause' role='button' onClick={pause}></img>
            <img src={stopIcon} className="control-btn" alt='stop' role='button' onClick={
              () => {
                const actualTime = getTime();
                stop(actualTime);
              }
              }></img>
            <img src={resetIcon} className="control-btn" alt='reset' role='button' onClick={reset}></img>
          </div>
        </>
    )}
</Timer>
  )
}

export default LogTimer;

If I log to the console 'actualTime' it properly has the value of the getTime() method when clicking the stop button.

But the component state is not updated. I've tried several other potential solutions, like trying to pass through props the "setTimerValue" function, but it doesn't work.

How can I solve this?

Thanks for your time.

5
  • I've checked this code and everything seems working, state is updating , .... Commented Apr 17, 2020 at 11:17
  • timerValue is updating in your case? Commented Apr 17, 2020 at 12:20
  • How you check timerValue?? setTimerValue is async, so you should check it's value via useEffect not directly after call to setTimerValue Commented Apr 17, 2020 at 12:26
  • I've tried to log it in the console, just after calling stop(actualTime) when clicking the stop button. But it seems that it doesn't reach the setTimerValue to actually update the state, so it returns null (the initial state) Commented Apr 17, 2020 at 12:32
  • I've found the problem, take a look at my answer and my codesandbox link. Commented Apr 17, 2020 at 13:07

1 Answer 1

1

Your problem is that you are sending actualTime via stop that is not possible, stop is just a method to notify Timer to stop so you can't send param to it. Update your code as follow:

<img
      className="control-btn"
      alt="stop"
      role="button"
      onClick={() => {
      const actualTime = getTime();
      setTimerValue(actualTime);
      stop();
     }}
/>

Also use useEffect to see updated value:

useEffect(() => {
    console.log("timerValue: " + timerValue);
}, [timerValue]);

My codesandbox link to see the updated code:https://codesandbox.io/s/react-hooks-counter-demo-o5ebq?file=/src/Timer.js

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.