【问题标题】:What is wrong with my React Native timer here?我的 React Native 计时器有什么问题?
【发布时间】:2020-04-09 22:48:58
【问题描述】:

我的代码旨在启动一个 20 分钟 -> 20:00 的计时器。我似乎在代码中遗漏了一些东西。当我在 Timer() 中调用它时,我的 setState 没有改变 time 的值:

class Sleep extends Component {
  // create constructor to get access to props
  constructor(props) {
    super(props);
    this.state = {
      time: 1200,
      timer: '',
    };
  }

  componentDidMount() {
    this.interval = setInterval(this.Timer(), 1000);
  }

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

  Timer() {
    console.log('time is ' + this.state.time);

    this.setState({
      time: this.state.time - 1,
    });

    console.log('time is ' + this.state.time);
    var timer;

    var minutes = Math.floor(this.state.time / 60);
    var seconds = this.state.time % 60;

    if (minutes < 10) {
      minutes = '0' + minutes.toString();
    }

    if (seconds < 10) {
      seconds = '0' + seconds.toString();
    }

    timer = minutes.toString() + ':' + seconds.toString();

    this.setState({
      timer: timer,
    });
  }

  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#FFFFFF', paddingBottom: 100 }}>
        <View>
          <Text style={styles.timerText}>{this.state.timer}</Text>
        </View>
      </View>
    );
  }
}

计时器应该每秒从 20:00 倒计时到 00:00。我输入了一些 console.log() 语句来尝试诊断问题。

【问题讨论】:

标签: javascript reactjs timer native


【解决方案1】:

Timer 函数定义没有绑定类的this,所以当它调用this.setState 时,它与组件的this 不同。您有 2 个选项。

选项1:在构造函数中将this绑定到Timer

constructor(props) {
  super(props);
  this.state = {
    time: 1200,
    timer: '',
  };
  this.Timer = this.Timer.bind(this);
}

方案2:使用ES6箭头函数自动绑定调用者的this

Timer = () => {...};

注意:按照惯例,函数名应该是驼峰式而不是帕斯卡式

您可以稍微简化您的组件逻辑。首先,显示的时间可以从数值time状态值推导出来,所以不需要同时存储两者。其次,看起来您正在尝试更新时间然后使用那个新时间来计算显示时间。 React 状态更新是异步的,因此下一个状态值要到下一个渲染周期才可用。

只需在setInterval 回调中更新状态并在渲染函数中计算派生的显示时间。

睡眠.jsx

class Sleep extends Component {
  state = {
    time: 60 * 20 // 20 minutes
  };

  componentDidMount() {
    this.interval = setInterval(
      // functional state update to ensure state is correctly updated
      // from previous state
      () => this.setState(({ time }) => ({ time: time - 1 })),
      1000
    );
  }

  componentDidUpdate() {
    const { time } = this.state;
    if (time <= 0) {
      clearInterval(this.interval);
    }
  }

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

  render() {
    const { time } = this.state;
    const minutes = String(Math.floor(time / 60)).padStart(2, "0");
    const seconds = String(time % 60).padStart(2, "0");

    return (
      <div>
        {minutes}:{seconds}
      </div>
    );
  }
}

【讨论】:

  • 好的,但是我应该在哪里插入时间 = 时间 - 1?如果我把它放在 setState 中它似乎不起作用
  • @radhadman 啊,我明白了。您正在尝试更新状态中的time,然后使用该值更新状态中的timer 值。更新了答案并附有解释。
  • 我的另一个问题是:为什么要在 componentDidUpdate() 方法中处理 (if time
  • @radhadman 这是一个生命周期函数,专门用于在状态/道具更新时处理。 render 函数应该是一个具有零副作用的纯函数,例如更新状态或进行 API 调用。
  • 我创建了一个贪睡按钮,该按钮在计时器到达 00:00 后启用,并让它工作,甚至无需更改 componentDidUpdate 中的任何内容。这是错误的做法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 2022-06-14
  • 1970-01-01
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多