一旦达到 0,在 React Native 中清除计时器的最佳方法是什么?

What's the best way to clear a timer in React Native once it gets to 0?

我这里有一个简单的计时器应用程序,有一天它可能会变成一个番茄钟应用程序。我现在正在学习生命周期方法。

问题来了。一旦达到 0,我想从屏幕上删除计时器。最终,它会立即被另一个计时器替换,但我还没有达到那个部分。我很确定问题出在这里:

componentDidUpdate = () => {
  if (this.state.count-1 === -2) {
    this.props.timerOverCallback()
  }
}

最初,我试过这个 if 语句:!(this.state.count-1)。计数器在 2 而不是 0 保持清零。

然后我尝试了 this.state.count-1 === -1 因为这似乎仍然有意义。计数器一直清零为 1 而不是 0。

到那时,一个模式已经出现,我尝试了this.state.count-1 === -2。我的问题是:为什么我需要与 -2 而不是 -1 进行比较?与 -2 相比似乎并不是特别可靠,真的。那么在 0 处清除计时器的最佳方法是什么?

完整代码如下:

class Timer extends Component {

  static propTypes = {
    timerOverCallback: PropTypes.func.isRequired,
    count: PropTypes.number.isRequired,
  }

  constructor(props) {
    super(props)
    this.state = {
      timerOverCallback: this.props.timerOverCallback,
      count: this.props.count,
    }
  }

  decrease = () => {
    this.setState(
        prevState => ({count: prevState.count - 1})
    )
  }

  componentDidMount = () => {
    this.interval = setInterval(this.decrease, 1000)
  }

  componentDidUpdate = () => {
    if (this.state.count-1 === -2) {
      this.props.timerOverCallback()
    }
  }

  componentWillUnmount = () => { clearInterval(this.interval) }

  render() {
    return (
      <Text style={styles.count}>{this.state.count}</Text>
    )
  }
}

export default class App extends Component {
  constructor() {
    super()
    this.state = {
      timerOn: false,
    }
  }

  toggleTimer = () => {
    this.setState(
      prevState => ({timerOn: !prevState.timerOn})
    )
  }

  render() {
    return (
      <View
        style={styles.fillAndCenter}>
        {this.state.timerOn ?
          <Timer
            count={5}
            timerOverCallback={this.toggleTimer}
          /> : <View/>
        }
        <Button
          title='Toggle Timer'
          onPress={this.toggleTimer}
        />
        <Text>
          {this.state.timerOn ? 'On' : 'Off'}
        </Text>
      </View>
    )
  }
}

2018 年 5 月 8 日更新:

我采纳了 gaback 的建议并放置了...

if (this.state.count < 0) this.state.timerOverCallback()

... 在 this.decrease 中并摆脱了 componentDidMount。但是,我意识到当 this.state.count = -1 时,组件实际上已进入其生命周期的渲染阶段,这似乎有问题。的确,屏幕从未真正更新到 -1,但渲染函数肯定被调用了,所以屏幕没有更新的事实似乎是巧合(对吧!?)。

然后我意识到,即使我过于挑剔,也有简单的方法可以解决这个问题:

shouldComponentUpdate = (nextProps, nextState) => {
  return nextState.count > -1
}

这是来自 React-Native 网站的componentDidUpdate

componentDidUpdate() is invoked immediately after updating occur

假设您的屏幕显示 0this.state.count = 0)this.decrease 获取调用 => this.state.count = -1 => 组件获取更新 => componentDidUpdate 获取调用 (在渲染之前所以屏幕仍然显示 0

this.state.count - 1 = -2,您调用 timeOverCallback() 并停止屏幕呈现当前 this.state.count,即 -1

您可以更改为 this.state.count === -1 或者我认为更好的方法是停止使用 componentDidUpdate,将支票放入 this.decrease:当您看到 this.state.count < 0 调用 timeOverCallback()