为什么在react中更新数据时计时器不能正常工作?

niwlg2el  于 2021-09-23  发布在  Java
关注(0)|答案(1)|浏览(279)

我的计时器(模式->组件更新->计时器)在更新数据(主->组件安装->计时器)后开始工作不正确-它开始工作得更快,并在最后输出-1。怎么了?如果删除数据更新(主->组件安装->计时器),计时器(模式->组件更新->计时器)工作正常。

import React, { Component } from 'react';

class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      isOpened: false
    };
    this.submitForm = this.submitForm.bind(this);
  }

  componentWillMount() {
    fetch('/api/global.json')
      .then(response => response.json())
      .then(result =>
        this.setState({
          data: result.data
          // get data
        }));
  }

  componentDidMount() {
    this.timer = setInterval(() => this.componentWillMount(), 10000);
  }

  componentWillUnmount() {
    this.timer = null;
  }

  changeModal = () => {
    this.setState({ isOpened: !this.state.isOpened });
  }

  submitForm(e) {
    e.preventDefault();
    this.setState({ isOpened: !this.state.isOpened });
  }

  render() {
    return (
      <div>
        <form onSubmit={this.submitForm}>
          <button className="button button-main" type="submit">Modal open</button>
        </form>
        <Modal isOpened={this.state.isOpened} changeModal={() => this.changeModal(this)} />
      </div>
    );
  }
}

class Modal extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 30 };
  }

  componentDidUpdate(prevProps) {
    if (prevProps.isOpened !== this.props.isOpened) {
      if (!this.props.isOpened) {
        this.setState({ counter: 30 });
        clearTimeout(this.timer);
      }
    }
    if (this.props.isOpened && this.state.counter > 0) {
      this.timer = setTimeout(() => this.setState({ counter: this.state.counter - 1 }), 1000);
    }
  }

  componentWillUnmount() {
    clearTimeout(this.timer);
  }

  render() {
    const padTime = time => {
      return String(time).length === 1 ? `0${time}` : `${time}`;
    };

    const format = time => {
      const minutes = Math.floor(time / 60);
      const seconds = time % 60;
      return `${minutes} мин ${padTime(seconds)} сек`;
    };

    return (
      <div className={"modal-overlay" + (this.props.isOpened ? " open" : " close")}>
        <div className='modal-content'>
          <div className='modal-close' onClick={() => this.props.changeModal()}>×</div>
          <div className="modal-note">{this.state.counter === 0 ? 'Finish!' : 'Timer ' + format(this.state.counter)}</div>
        </div>
      </div>
    )
  }
}

export default Main;
yxyvkwin

yxyvkwin1#

当我在等待最佳解决方案时,我做了以下工作,它起了作用-更新主组件后,模式窗口中的计数器不会加速。但我不确定这是否是正确的解决方案。我期待你的帮助。

class Modal extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 30 };
  }

  componentDidMount() {
    if (this.state.counter > 0) {
      this.timer = setInterval(() => this.setState({ counter: this.state.counter > 0 ? this.state.counter - 1 : 0}), 1000);
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.isOpened !== this.props.isOpened) {
      if (this.props.isOpened) {
        this.setState({ counter: 30 });
      }
    }
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    const padTime = time => {
      return String(time).length === 1 ? `0${time}` : `${time}`;
    };

    const format = time => {
      const minutes = Math.floor(time / 60);
      const seconds = time % 60;
      return `${minutes} мин ${padTime(seconds)} сек`;
    };

    return (
      <div className={"modal-overlay" + (this.props.isOpened ? " open" : " close")}>
        <div className='modal-content'>
          <div className='modal-close' onClick={() => this.props.changeModal()}>×</div>
          <div className="modal-note">{this.state.counter === 0 ? 'Finish!' : 'Timer ' + format(this.state.counter)}</div>
        </div>
      </div>
    )
  }
}

相关问题