setInterval в обещании, выполняется только один раз в React - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь создать таймер обратного отсчета с одной тикающей секундой каждую секунду. Интервал работает только один раз и не выполняется. Проблема в том, что у меня нет this.state.time до тех пор, пока не будет сделан серверный вызов , тогда я могу запустить таймер. Следовательно, функция setInterval должна быть скрыта в обещании, где она выполняет только одно. Однако переменная timetill может быть константой, после извлечения она не изменяется.

componentDidMount = async () => {
const that = this;
*do stuff*
this.someFunction().finally(() => {
/*This right here, below is not working */
setInterval(that.createTimer(), 1000);  
});
}

Моя JSX - это такая

{this.state.setTimer}

функция, о которой идет речь, время нужно разделить на 1000, поскольку javascript использует милисекунды

createTimer = async timerNow => {
var timerNow = (await new Date().getTime()) / 1000;
// Find the distance between now and the count down date
var distance = this.state.timeTill - timerNow;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
//the variable displayed
var setTimer = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
this.setState({setTimer});
};

Ответы [ 2 ]

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

Вы передаете возвращенное значение createTimer в setInterval, вместо этого передаете функцию, но не вызываете ее

setInterval(this.createTimer, 1000)

0 голосов
/ 02 апреля 2020

Есть несколько вещей, которые вы должны сделать: 1. У вас должен быть метод, который будет фактически вызывать setState 2. Измените setInterval для вызова метода reference 3. Очистите все отложенные запросы при размонтировании: 4 . [опционально] вы можете сбросить that


private createTimer = { ... }

private setTimer = () => {
  this.setState({ timer: this.createTimer() });
}

private _mounted: boolean = false;
private _intervalHandler: number | null = null;

componentDidMount = async () => {

  this._mounted = true;

  this.someFunction().finally(() => {
    if (!this._mounted) { return; }

    this._intervalHandler = setInterval(this.setTimer, 1000);  
  });
}

componentWillUnmoun = () => {
  this._mounted = false;
  if (this._intervalHandler !== null) {
    clearInterval(this._intervalHandler);
  }
}

Это гарантирует, что вы не будете выполнять изменения состояния после размонтирования компонента.

...