我在React还是比较新的,但是我一直在慢慢地磨,而且我遇到了一些我坚持不懈的事情。
我正在尝试构建一个"计时器" React中的组件,说实话,我不知道我是否正确(或有效)这样做。在我的下面的代码中,我将状态设置为返回一个对象{ currentCount: 10 }
,并且一直在玩componentDidMount
,componentWillUnmount
和render
,我只能将状态设置为& #34;倒数"从10到9。
由两部分组成的问题:我出错了什么?并且,是否有更有效的方法来使用setTimeout(而不是使用componentDidMount
& componentWillUnmount
)?
提前谢谢。
import React from 'react';
var Clock = React.createClass({
getInitialState: function() {
return { currentCount: 10 };
},
componentDidMount: function() {
this.countdown = setInterval(this.timer, 1000);
},
componentWillUnmount: function() {
clearInterval(this.countdown);
},
timer: function() {
this.setState({ currentCount: 10 });
},
render: function() {
var displayCount = this.state.currentCount--;
return (
<section>
{displayCount}
</section>
);
}
});
module.exports = Clock;
答案 0 :(得分:124)
我发现您的代码有4个问题:
setState
方法实际更改状态让我们试着解决这个问题:
componentDidMount: function() {
var intervalId = setInterval(this.timer, 1000);
// store intervalId in the state so it can be accessed later:
this.setState({intervalId: intervalId});
},
componentWillUnmount: function() {
// use intervalId from the state to clear the interval
clearInterval(this.state.intervalId);
},
timer: function() {
// setState method is used to update the state
this.setState({ currentCount: this.state.currentCount -1 });
},
render: function() {
// You do not need to decrease the value here
return (
<section>
{this.state.currentCount}
</section>
);
}
这将导致计时器从10减少到-N。如果您希望计时器减少到0,则可以使用稍加修改的版本:
timer: function() {
var newCount = this.state.currentCount - 1;
if(newCount >= 0) {
this.setState({ currentCount: newCount });
} else {
clearInterval(this.state.intervalId);
}
},
答案 1 :(得分:24)
使用class Clock extends Component
import React, { Component } from 'react';
class Clock extends Component {
constructor(props){
super(props);
this.state = {currentCount: 10}
}
timer() {
this.setState({
currentCount: this.state.currentCount - 1
})
if(this.state.currentCount < 1) {
clearInterval(this.intervalId);
}
}
componentDidMount() {
this.intervalId = setInterval(this.timer.bind(this), 1000);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
render() {
return(
<div>{this.state.currentCount}</div>
);
}
}
module.exports = Clock;
答案 2 :(得分:6)
使用 Hooks (新的功能建议,使您无需编写类即可使用状态和其他React功能。它们当前在React v16.7.0-alpha中)更新了10秒倒计时。 / p>
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
const Clock = () => {
const [currentCount, setCount] = useState(10);
const timer = () => setCount(currentCount - 1);
useEffect(
() => {
if (currentCount <= 0) {
return;
}
const id = setInterval(timer, 1000);
return () => clearInterval(id);
},
[currentCount]
);
return <div>{currentCount}</div>;
};
const App = () => <Clock />;
ReactDOM.render(<App />, document.getElementById('root'));
答案 3 :(得分:5)
如果有人正在寻找React Hook方法来实现setInterval。丹·阿布拉莫夫(Dan Abramov)在他的blog上谈到了这一点。如果您想很好地了解该主题(包括“课堂”方法),请检查一下。基本上,代码是一个自定义的Hook,它将setInterval变为声明性的。
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
为方便起见,还发布了CodeSandbox链接:https://codesandbox.io/s/105x531vkq
答案 4 :(得分:2)
使用React Hooks管理setInterval:
const [seconds, setSeconds] = useState(0)
const interval = useRef(null)
useEffect(() => { if (seconds === 60) stopCounter() }, [seconds])
const startCounter = () => interval.current = setInterval(() => {
setSeconds(prevState => prevState + 1)
}, 1000)
const stopCounter = () => clearInterval(interval.current)
答案 5 :(得分:0)
感谢@ dotnetom,@ greg-herbowicz
如果返回“ this.state未定义”-绑定计时器功能:
constructor(props){
super(props);
this.state = {currentCount: 10}
this.timer = this.timer.bind(this)
}
答案 6 :(得分:0)
每隔一秒钟更新一次react类的状态。请注意,我的index.js传递了一个返回当前时间的函数。
import React from "react";
class App extends React.Component {
constructor(props){
super(props)
this.state = {
time: this.props.time,
}
}
updateMe() {
setInterval(()=>{this.setState({time:this.state.time})},1000)
}
render(){
return (
<div className="container">
<h1>{this.state.time()}</h1>
<button onClick={() => this.updateMe()}>Get Time</button>
</div>
);
}
}
export default App;
答案 7 :(得分:0)
最简单的方法是将其添加到 window 变量中。
useEffect(() => {
window.interval23 = setInterval(
() => setState('something'),
2500
)
return () => {
clearInterval(window.interval23)
}
}, [])
但是请确保您使用 window 变量创建的任何内容都尽可能保持唯一性,因为如果该变量已经存在,window 变量可能会在库中中断。