Таймер обратного отсчета не может выполнить функцию остановки - PullRequest
1 голос
/ 04 мая 2020

Я практически новичок в React. В этом приложении я использую крючки! Я сделал таймер обратного отсчета, который будет отображаться через несколько секунд после входа в систему. Я не могу остановить его при нажатии кнопки. Мне нужно несколько советов по этому поводу, так как я боролся с этим в течение последних 2 дней. Это мой код: (Пожалуйста, помогите)

function Admin() {
    const [isTimerOpen, setTimmer] = useState(false);
    let history = useHistory();

    // SET BY THE ADMIN
    var minutesToCountDown = 0.9;
    // TRANSFORM INTO SECONDS
    var transformMinutesToSeconds = minutesToCountDown * 60
    // KEEP A STATE
    const [counterValue, setCounterValue] = useState(0);
    const [isTimmerStoped, setStopTimer] = useState(false);

    // FUNCTION TO HAPPEN EVERY 1 SECOND
    function timeIt() {
        if (isTimmerStoped === false) {
            transformMinutesToSeconds--
            setCounterValue(transformMinutesToSeconds)
            console.log("Timer is on: ", transformMinutesToSeconds)

            if (transformMinutesToSeconds === 0) {
                clearInterval(interval)
                setStopTimer(true)
            }
        } else {
            setStopTimer(true)
            clearInterval(interval)
        }
    }

    // STARTS THE COUNTDOWN
    var interval;
    const startCountdown = () => {
        interval = setInterval(timeIt, 1000)
    }

    const stopCountdown = () => {
        console.log("Stop Timer")
        setStopTimer(true);
        setCounterValue(0);
        setTimmer(false);
    }

    // ADD 0 IN FRONT ON THE TIME REMAINING
    const addLeadingZeros = value => {
        value = String(value);
        while (value.length < 2) {
            value = `0${value}`;
        }
        return value;
    };

    // CONVERT SECONDS INTO TIME REMAINING
    function convertSeconds(seconds) {
        var min = Math.floor(seconds / 60);
        var sec = seconds % 60;
        return addLeadingZeros(min) + ':' + addLeadingZeros(sec)
    }

    const logOutUser = () => {
        logout();
        return history.push(mainRoute)
    }

    function setTimer() {
        const timer = setTimeout(() => {
            setTimmer(true)
            console.log('This will run after 3 seconds!')
            startCountdown()

        }, sessionTimeout);
        return () => clearTimeout(timer);
    }

    useEffect(() => {
        if (isTimmerStoped === false) {
            console.log('Effect Starting', isTimmerStoped)
            setTimer()
        } else {
            console.log('Effect Stopping', isTimmerStoped)
            stopCountdown()
        }

      }, [isTimmerStoped, setStopTimer, minutesToCountDown]);



    return <React.Fragment>
            <CssBaseline />
            <Container disableGutters maxWidth={false}>
                <NavigationBar handleSignOut={logOutUser}/>
                <TimerContent 
                    timeRemaining={convertSeconds(counterValue)}
                    isTimerAlertOpen={isTimerOpen}
                    extendSessionBtn={stopCountdown}
                    logoutBtn={logOutUser}  
                    clickOutsideButton={stopCountdown}/>
            </Container>
    </React.Fragment>  
}

export default Admin;

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Вы должны сделать 2 вещи.

  1. Переместить переменную interval вне области действия вашей функции, например
let interval;
function Admin() {
  //... code here

  // STARTS THE COUNTDOWN
  // var interval; Remove from here
  const startCountdown = () => {
      interval = setInterval(timeIt, 1000)
  }

  //... code here
}

export default Admin;
Добавьте clearInterval к вашей функции stopCountdown. Вы можете удалить clearInterval в функции timeIt и переместить его в stopCountdown. Пожалуйста, взгляните на этот кодовый блок , который я сделал для демонстрации
const stopCountdown = () => {
  console.log("Stop Timer")
  setStopTimer(true);
  setCounterValue(0);
  setTimmer(false);
  clearInterval(interval) // Clear the interval here
}
1 голос
/ 04 мая 2020

Не следует поддерживать интервал, возвращаемый setInterval, в функциональной переменной, поскольку он будет сброшен при повторном рендеринге, и вы потеряете фактический идентификатор таймера. Вместо этого вы должны использовать useRef hook для хранения timerId

   const interval = useRef(null);
    ...
   function timeIt() {
        if (isTimmerStoped === false) {
            transformMinutesToSeconds--
            setCounterValue(transformMinutesToSeconds)
            console.log("Timer is on: ", transformMinutesToSeconds)

            if (transformMinutesToSeconds === 0) {
                clearInterval(interval.current)
                setStopTimer(true)
            }
        } else {
            setStopTimer(true)
            clearInterval(interval.current)
        }
    }
    ...
   // STARTS THE COUNTDOWN
    const startCountdown = () => {
        interval.current = setInterval(timeIt, 1000)
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...