我一直在使用React并使用以下时间组件将Date.now()
呈现给屏幕:
import React, { Component } from 'react';
class TimeComponent extends Component {
constructor(props){
super(props);
this.state = { time: Date.now() };
}
render(){
return(
<div> { this.state.time } </div>
);
}
componentDidMount() {
console.log("TimeComponent Mounted...")
}
}
export default TimeComponent;
从React的角度来看,让这个组件每秒更新以重新绘制时间的最佳方法是什么?
答案 0 :(得分:76)
您需要使用setInterval
来触发更改,但您还需要在组件卸载时清除计时器,以防止错误和泄漏内存:
componentDidMount() {
this.interval = setInterval(() => this.setState({ time: Date.now() }), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
答案 1 :(得分:75)
这是React.js网站的一个例子:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
tick() {
this.setState(prevState => ({
seconds: prevState.seconds + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
答案 2 :(得分:20)
@Waisky建议:
您需要使用
setInterval
来触发更改,但是还需要在卸载组件时清除计时器,以防止它留下错误和内存泄漏:
如果您想做同样的事情,请使用Hooks:
const [time, setTime] = useState(Date.now());
useEffect(() => {
const interval = setInterval(() => setTime(Date.now()), 1000);
return () => {
clearInterval(interval);
};
}, []);
关于评论:
您无需在[]
内部传递任何内容。如果您在括号中传递time
,则意味着time
的值每次更改都会运行效果,即,setInterval
每次更改都会调用一个新的time
,这不是我们想要的。我们只希望在安装组件时调用一次setInterval
,然后setInterval
每1000秒调用一次setTime(Date.now())
。最后,在卸载组件时,我们调用clearInterval
。
请注意,每次time
的值更改时,组件都会根据您在其中使用time
的方式进行更新。这与将time
放在[]
的{{1}}中无关。
答案 3 :(得分:6)
在组件的componentDidMount
生命周期方法中,您可以设置一个间隔来调用更新状态的函数。
componentDidMount() {
setInterval(() => this.setState({ time: Date.now()}), 1000)
}
答案 4 :(得分:3)
我自己更喜欢setTimeout
而不是setInterval
,但是在基于类的组件中没有找到解决方案。你可以在基于类的组件中使用这样的东西:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date()
};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
this.state.date.toLocaleTimeString()
);
}
}
ReactDOM.render(
<Clock / > ,
document.getElementById('app')
);
<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="app" />
https://codesandbox.io/s/sweet-diffie-wsu1t?file=/src/index.js
答案 5 :(得分:2)
class ShowDateTime extends React.Component {
constructor() {
super();
this.state = {
curTime : null
}
}
componentDidMount() {
setInterval( () => {
this.setState({
curTime : new Date().toLocaleString()
})
},1000)
}
render() {
return(
<div>
<h2>{this.state.curTime}</h2>
</div>
);
}
}
答案 6 :(得分:0)
所以您走在正确的轨道上。在componentDidMount()
内部,您可以通过实现setInterval()
来触发更改来完成工作,但是请记住,通过setState()
更新组件状态的方法是,所以在componentDidMount()
内部您可以这样做:
componentDidMount() {
setInterval(() => {
this.setState({time: Date.now()})
}, 1000)
}
此外,您可以使用Date.now()
并与我上面提供的componentDidMount()
实现一起使用,但是您将获得大量令人讨厌的数字更新,这是人类无法理解的,但是从技术上讲,这是时候自1970年1月1日以来,以毫秒为单位进行更新,但是我们希望使这一时间对人类阅读时间的方式具有可读性,因此除了学习和实现setInterval
之外,您还想了解new Date()
和{ {1}},您将像这样实现它:
toLocaleTimeString()
注意,我还删除了class TimeComponent extends Component {
state = { time: new Date().toLocaleTimeString() };
}
componentDidMount() {
setInterval(() => {
this.setState({ time: new Date().toLocaleTimeString() })
}, 1000)
}
函数,您不一定需要它,我的重构相当于100%等效于使用constructor()
函数初始化站点。
答案 7 :(得分:0)
由于已弃用componentWillReceiveProps()的React V16中的更改,这是我用于更新组件的方法。 请注意,以下示例在Typescript中,并且在更新Props时使用静态getDerivedStateFromProps方法获取初始状态和更新状态。
class SomeClass extends React.Component<Props, State> {
static getDerivedStateFromProps(nextProps: Readonly<Props>): Partial<State> | null {
return {
time: nextProps.time
};
}
timerInterval: any;
componentDidMount() {
this.timerInterval = setInterval(this.tick.bind(this), 1000);
}
tick() {
this.setState({ time: this.props.time });
}
componentWillUnmount() {
clearInterval(this.timerInterval);
}
render() {
return <div>{this.state.time}</div>;
}
}