Home > front end >  UseState not updating Component property
UseState not updating Component property

Time:10-31

I'm working on a project where I'm playing with a react-countdown-circle-timer and useState. I'm trying to add a button to start / stop and I'd like when I stop the countdown to reset to initial value. However, the stop happens, but the time is not reset, unless I navigate to another item and back. I'm new with react and I'm not having a complete understanding of how useEffect and useState works. Please help me out. Thank you.

import { Card, Col, Row } from "react-bootstrap";
import { CountdownCircleTimer } from "react-countdown-circle-timer";
import { useEffect, useState } from "react";

const formatRemainingTime = (time) => {
  const minutes = Math.floor((time % 3600) / 60);
  let seconds = time % 60;
  if (seconds < 10 && seconds > -1) {
    seconds = `0${seconds}`;
  }

  return `${minutes}:${seconds}`;
};

const renderTime = ({ remainingTime }) => {
  return (
    <div className={classes.timer}>
      <div className={classes.text}>Remaining</div>
      <div className={classes.value}>{formatRemainingTime(remainingTime)}</div>
      <div className={classes.text}></div>
    </div>
  );
};

function MainItem(props) {
  const [totalDuration, setTotalDuration] = useState(0);
  const [timerOn, setTimerOn] = useState(false);

  useEffect(() => {
    const myDuration =
      parseInt(props.item.red.split(":")[0]) * 60  
      parseInt(props.item.red.split(":")[1])  
      30;
    setTotalDuration(myDuration);
  }, [props]);

  const startHandler = () => {
    setTimerOn(true);
  };
  const stopHandler = () => {
    setTimerOn(false);
  };

  const resetHandler = () => {
    setTimerOn(false);
    setTotalDuration(totalDuration)
  };

  return (
    <Row>
      <Col>
        <Card>
          <Card.Body>
            <Row>
              <Col>
                <div>
                  <button onClick={startHandler}>Start</button>
                  <button onClick={stopHandler}>Pause</button>
                  <button onClick={resetHandler}>Reset</button>
                </div>
              </Col>
              <Col className={classes.timer_wrapper}>
                <CountdownCircleTimer
                  key={totalDuration}
                  isPlaying={timerOn}
                  duration={totalDuration}
                  size={300}
                  strokeWidth={20}
                  trailColor={"#363537"}
                  colors={[
                    ["#42b0f5", 0.5],
                    ["#42b0f5", 0.01],
                    ["#2bb32b", 0.2],
                    ["#2bb32b", 0.01],
                    ["#eeee60", 0.2],
                    ["#eeee60", 0.01],
                    ["#ff4a2e"],
                  ]}
                  onComplete={() => [true, 1000]}
                >
                  {renderTime}
                </CountdownCircleTimer>
              </Col>
            </Row>
          </Card.Body>
        </Card>
      </Col>
    </Row>
  );
}
export default MainItem;

CodePudding user response:

React can realize, that you don't actually change totalDuration. Therefore, no event is triggered to update the key prop in the CountdownCircleTimer. You should create another key like

const [key, setKey] = useState(false)
...
<CountdownCircleTimer key={key} ... />

A function, that resets the timer would be

const reset = () => setKey(val => !val)

That way, every time reset() is called, val is changed and therefore an update on key is triggered.

  • Related