setInterval и clearInterval не работают вместе - PullRequest
0 голосов
/ 23 апреля 2020

Итак, у меня есть функции setInterval и clearInterval для запуска и остановки счетчика соответственно. Проблема здесь в том, что каждый раз, когда я нажимаю кнопку, состояние устанавливается в значение true, и запускается функция таймера, которая запускает таймер. Теперь при повторном нажатии на таймер таймер не останавливается, поскольку переменная refreshIntervalId теперь имеет значение undefined. Пожалуйста, помогите мне в этом, пожалуйста!

Вот мой код:

  if (timer == true) {
    console.log("timer is playing");
    refreshIntervalID = setInterval(timerFunction, 1000);
    console.log(refreshIntervalID);
  }

  if (timer == false) {
    console.log(refreshIntervalID);
    clearInterval(refreshIntervalID);
  }

Вот полный код:

import React from "react";
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
import { playToggle, reset } from "./actions/indexAction";

function Timer() {
  const timer = useSelector((state) => state.timer);
  const sessionLength = useSelector((state) => state.sessionLength);

  let minutes = sessionLength;
  let seconds = 60;
  var refreshIntervalID;

  const dispatch = useDispatch();

  let resetClick = () => {
    return dispatch(reset());
  };

  let timerFunction = () => {
    if (timer == true) {
      seconds--;
      console.log(seconds);
    }
  };

  if (timer == "reset") {
    minutes = sessionLength;
    seconds = 60;
    console.log("Is Reset");
  }

  if (timer == true) {
    console.log("timer is playing");
    refreshIntervalID = setInterval(timerFunction, 1000);
    console.log(refreshIntervalID);
  }

  if (timer == false) {
    console.log(refreshIntervalID);
    clearInterval(refreshIntervalID);
  }

  return (
    <div>
      <h1>Minutes: {minutes}</h1>
      <h1>Minutes: {seconds}</h1>
      <div>
        <button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
      </div>
      <div>
        <button onClick={resetClick}>RESET</button>
      </div>
    </div>
  );
}

export default Timer;

1 Ответ

1 голос
/ 23 апреля 2020

Это не совсем актуально, так как комментарий, с которым это было связано, оказался не совсем точным:

Вы абсолютно не хотите иметь побочные эффекты в редукторном редукторе. Вместо этого сделайте побочные эффекты в компоненте. Причина в том, что редукторы должны быть чистыми, чтобы вся архитектура потока работала правильно. Единственный раз, когда в редукторе должны быть побочные эффекты, это если вы используете промежуточное программное обеспечение, такое как redux-l oop. В противном случае вы можете быстро получить некоторый очень не поддерживаемый код.

Если это функциональный компонент, вот как я это делаю:

function(){
  useEffect(()=>{
    if (timer) {
      console.log("timer is playing");
      const refreshIntervalID = setInterval(timerFunction, 1000);
      console.log(refreshIntervalID);
      return ()=>{
        clearInterval(refreshIntervalID)
      }
    }
  },[timer])
}

Вы должны очистить интервал в хуке useEffect

Редактировать: добавить, надеюсь, рабочий код

import React, { useEffect, useState } from 'react';
import './App.css';
import { useSelector, useDispatch } from 'react-redux';
import { playToggle } from './actions/indexAction';

function Timer() {
  const timer = useSelector((state) => state.timer);
  const sessionLength = useSelector((state) => state.sessionLength * 60); // session in seconds
  const [seconds, setSeconds] = useState(sessionLength);
  const [resetTimer, setResetTimer] = useState(0);

  const dispatch = useDispatch();

  let resetClick = () => {
    // Get a new value every time
    setSeconds(sessionLength);
    setResetTimer((value) => value + 1);
  };
  useEffect(()=>{
    // Set the timer to use the latest value when the session length changes.
    setSeconds(sessionLength)
  },[sessionLength])

  useEffect(() => {
    // Perform a side effect
    if (timer) {
      // Only run the timer when timer is truthy
      let timerFunction = () => {
        setSeconds((seconds) => seconds - 1);
      };
      console.log('timer is playing');
      const refreshIntervalID = setInterval(timerFunction, 1000);
      return () => {
        // Clean up timer before effect runs again (or on unmount)
        clearInterval(refreshIntervalID);
      };
    }
    // Restart timer whenever timer, sessionLength, or resetTimer changes
  }, [timer, resetTimer]);

  useEffect(() => {
    // If the timer has elapsed, stop the timer and reset.
    if (seconds <= 0) {
      dispatch(playToggle());
      setSeconds(sessionLength);
    }
  }, [seconds, dispatch, sessionLength]);

  return (
    <div>
      <h1>Minutes: {Math.floor(seconds / 60)}</h1>
      <h1>Minutes: {seconds % 60}</h1>
      <div>
        <button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
      </div>
      <div>
        <button onClick={resetClick}>RESET</button>
      </div>
    </div>
  );
}

export default Timer;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...