在React中使用setInterval时遇到一些问题。
基本上,我正在尝试为FreeCodeCamp构建一个Pomodoro计时器,而setInterval无法识别该函数已定义。.下面的链接。
https://codepen.io/paalpwmd/pen/yLNJEMv?editors=1111
基本上-我希望计时器方法从总长度状态中减去1000ms,直到长度为0。
我得到的错误是这个。
TypeError: this.tick is not a function
at https://cdpn.io/boomboom/v2/index.html?editors=1111&key=iFrameKey-713a6d83-4480-ba30-a898-c7e72b527740:28
我也尝试过将set interval函数直接放在计时器内部(像这样),但我收到一条错误消息,说this.state是未定义的。
timer(){
setInterval(function() {
this.setState({
length: this.state.length - 1000
}), 1000)
}
我已经尝试了ES6和ES5语法,这在构造函数中是必不可少的。
我认为这与React绑定它的方式有关。我在这里做什么错了?
答案 0 :(得分:1)
将setInterval
回调function
更改为arrow function
。
当setInterval
将调用回调函数时,this
将引用setInterval object
。
如果状态更新取决于先前的状态,请始终在setState中使用
callback
。
尝试一下。
timer() {
setInterval(() => {
this.tick();
console.log("tick");
}, 1000)
}
工作示例:
class PomTimer extends React.Component {
constructor(props) {
super(props)
this.state = {
break: 300000,
length: 1500000,
clockFace: ''
}
this.clockify = this.clockify.bind(this);
this.timer = this.timer.bind(this);
this.reset = this.reset.bind(this);
this.tick = this.tick.bind(this);
}
reset() {
this.setState({
break: 300000,
length: 1500000
})
this.clockify();
}
tick() {
//console.log("tick: " + this.state.length);
if (this.state.length > 0) {
this.setState( (preState) => {
return {
length: preState.length - 1000
}
})
} else {
}
}
clockify() {
let minutes = Math.floor(this.state.length / 60000);
let seconds = (this.state.length % 60000) / 1000
this.setState({
clockFace: `${minutes}:${seconds}`
})
}
timer() {
setInterval(() => {
this.tick();
}, 1000)
}
componentDidMount() {
this.clockify();
}
render() {
return <div>
<h1>Pomodoro Clock</h1>
<div id="break-label">
<div id="break-increment" onClick={this.breakInc}>+</div>
<p id="break-length">Break Length: {this.state.break / 60000}</p>
<div id="break-decrement" onClick={this.breakDec}>-</div>
</div>
<div id="session-label">
<div id="session-increment" onClick={this.sessionInc}> + </div>
<p id="session-length">Session Length {Math.ceil(this.state.length / 60000)} ({this.state.length})</p>
<div id="session-decrement" onClick={this.sessionDec}> - </div>
</div>
<div id="session">
<p id="time-left"> Session: {this.state.clockFace} </p>
</div>
<button onClick={this.clockify}>test</button>
<button onClick={this.resetTimer}>Reset</button>
<button onClick={this.timer}>Timer</button>
</div>
}
}
ReactDOM.render(<PomTimer />, document.getElementById("react-root"));
#react-root {
width: 50%;
display: flex;
margin: auto;
border: 2px solid black;
border-radius: 50px;
justify-content: center;
}
body {
background-color: #1E555C;
font-family: 'Verdana'
}
#break-increment, #break-decrement, #session-increment, #session-decrement{
cursor: pointer;
margin: 0px 5px;
border: 1px solid black;
border-radius: 5px;
width: 20px;
height: 20px;
text-align: center;
background-color: #1E777C;
}
#session-label, #break-label, #session {
display: flex;
flex-direction: row;
justify-content: center;
padding-top: 50px;
}
#break-length, #session-length{
margin: 0;
}
#time-left {
font-size: 2rem;
}
<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>
<div id="react-root">