我正在编写一个简单的番茄计时器,只需单击一下按钮即可将其触发。
tick() {
if (this.state.minutes > 0) {
setInterval(() => {
this.timer(this.state.minutes * 60 + this.state.seconds - 1);
}, 1000);
}
}
timer(x) {
this.setState(
{
minutes: Math.trunc(x),
seconds: (x*60) % 60
},
() => this.tick()
);
}
render() {
return (
<div className="App">
<div className="Pomodo">
<div className="counter">
{this.state.minutes + ":" + this.state.seconds}
</div>
<button className="btnCode" onClick={() => this.timer(25)}>
Code
</button>
<button className="btnCoffee" onClick={() => this.timer(5)}>
Coffee
</button>
</div>
</div>
);
}
}
export default App;
这显示计时器如下:
25:00(正确)
24:59(正确)
24:57 ==错误应该是58
24:53 ==错误应该是57
...等
我在这里想念什么?通过Chrome进行故障排除时,计数器可以正常显示正确的数字。
答案 0 :(得分:1)
之所以跳过秒,是因为每次调用tick()
时,您都需要通过调用this.tick()
中的setState
来设置新的间隔。您可以通过在首次调用tick之后添加一个标志来解决此问题。
我看到的另一个问题是,您在btnCode的onClick
中将25
作为分钟传递给this.timer
。但是,在setInterval中,您将以秒为单位调用计时器。我建议您以秒为单位将所有内容传递给计时器功能。另外,最好在卸载时清除间隔。
请参阅调整后的代码。
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.state = {
minutes: 0,
seconds: 0,
started: false
}
this.tick = this.tick.bind(this);
this.timer = this.timer.bind(this);
}
tick() {
// Add flag so that tick is not called again
this.setState({
started: true
})
if (this.state.minutes > 0) {
this.interval = setInterval(() => {
const seconds = this.state.minutes * 60 + this.state.seconds - 1;
this.timer(seconds);
}, 1000);
}
}
componentWillUnmount() {
clearInterval(this.interval);
}
timer(x) {
this.setState(
{
minutes: Math.trunc(x / 60),
seconds: x % 60
},
() => !this.state.started && this.tick() // only call if its timer is not started before
);
}
render() {
return (
<div className="App">
<div className="Pomodo">
<div className="counter">
{this.state.minutes + ":" + this.state.seconds}
</div>
<button className="btnCode" onClick={() => this.timer(25 * 60)}>
Code
</button>
<button className="btnCoffee" onClick={() => this.timer(5 * 60)}>
Coffee
</button>
</div>
</div>
);
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>