一旦达到 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
假设您的屏幕显示 0
(this.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()
我这里有一个简单的计时器应用程序,有一天它可能会变成一个番茄钟应用程序。我现在正在学习生命周期方法。
问题来了。一旦达到 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
假设您的屏幕显示 0
(this.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()