Reputation: 355
I've got a clock function that gets time and renders out the hours, minutes and seconds, and I'm trying to update the data on screen in real time, but for some reason my setInterval function isn't doing what I expect.
I thought react's render method is supposed to render data in real time. Do I need ajax for this? Can anyone offer some advice?
var CityRow = React.createClass({
render: function() {
var currentdate = new Date();
function getTime() {
// get local time based on the UTC offset
this.hours = currentdate.getUTCHours() + parseInt(this.props.UTCOffset);
// correct for number over 24, and negatives
if( this.hours >= 24 ){ this.hours = this.hours - 24; }
if( this.hours < 0 ){ this.hours = this.hours + 12; }
// add leading zero, first convert hours to string
this.hours = this.hours + "";
if( this.hours.length == 1 ){ this.hours = "0" + this.hours; }
// minutes are the same on every time zone
this.minutes = currentdate.getUTCMinutes();
// add leading zero, first convert hours to string
this.minutes = this.minutes + "";
if( this.minutes.length == 1 ){ this.minutes = "0" + this.minutes; }
this.seconds = currentdate.getUTCSeconds();
}
window.setInterval(function () {
getTime();
}, 1000);
return(
<div className="city-row" ref="cityRow">
<span className="city-time">{this.hours}:{this.minutes}:{this.seconds}</span>
</div>
</div>
)
}
});
Upvotes: 8
Views: 32618
Reputation: 467
functional component
function Time() {
const [time, setTime] = React.useState(new Date());
React.useEffect(() => {
setInterval(() => {
setTime(new Date());
}, 1000);
}, []);
return <span>{time.toLocaleString("en-US", {
dateStyle: "full",
timeStyle: "medium",
hour12: false,
})} </span>;
}
Upvotes: 1
Reputation: 111
import React, { Component } from "react";
class Clock extends Component {
constructor (props) {
super(props);
this.state = {
dateClass: new Date()
}
this.time = this.state.dateClass.toLocaleTimeString();
this.hourMin = this.time.length === 10? this.time.slice(0) : this.time.slice(0,5);
}
setTime = () => {
this.setState({
dateClass: new Date()
})
this.time = this.state.dateClass.toLocaleTimeString();
this.hourMin = this.time.length === 10? this.time.slice(0) : this.time.slice(0,5);
}
componentDidMount () {
setInterval(this.setTime, 1000)
}
render () {
return (
<div>
{this.hourMin}
</div>
)
}
}
export default Clock;
Hey, I have more simple approach.
Upvotes: 0
Reputation: 1
class Clock extends React.Component {
state ={time:null}
componentDidMount() {
setInterval(() => {
this.setState({time:new Date().toLocaleTimeString()})}, 1000)
}
render() {
return (
<div className="time">
The time is: {this.state.time}
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root') );
Upvotes: 0
Reputation: 581
Update of "TheSchecke" answer to show UTC date on format "YYYY-MM-DD HH:mm:ss":
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() {
const ISOStringDate = this.state.date.toISOString();
return (
<div>
<h1>UTC Time:</h1>
<h2>{ISOStringDate.substring(0, 19).replace('T', ' ')}</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
Upvotes: 0
Reputation: 1144
The official React Docs describe exactly what you need (and even explains why you should do it as described):
--> React Docs: State and Lifecycle
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 (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
Upvotes: 16
Reputation: 3300
There seems to be a couple problems with your code. First is the closing div in the render function which causes your element to not even render.
Next you might want to take a look at state/props and React general lifecycle methods to get a better idea of program flow. The setInterval should be put in componentDidMount so its not called every time your component renders and creates a lot of timers. It also might help to put hours, minutes, and seconds as state so that way when these change your component re-renders automatically.
I modified your code below and put an example on jsfiddle. It does not print the seconds properly (just like in your getTime method) but hopefully it will give you a better idea of how logic should flow.
https://jsfiddle.net/rpg6t4uc/
var CityRow = React.createClass({
setTime: function(){
var currentdate = new Date();
var hours = currentdate.getUTCHours() + parseInt(this.props.UTCOffset);
// correct for number over 24, and negatives
if( hours >= 24 ){ hours -= 24; }
if( hours < 0 ){ hours += 12; }
// add leading zero, first convert hours to string
hours = hours + "";
if( hours.length == 1 ){ hours = "0" + hours; }
// minutes are the same on every time zone
var minutes = currentdate.getUTCMinutes();
// add leading zero, first convert hours to string
minutes = minutes + "";
if( minutes.length == 1 ){ minutes = "0" + minutes; }
seconds = currentdate.getUTCSeconds();
console.log(hours, minutes, seconds)
this.setState({
hours: hours,
minutes: minutes,
seconds: seconds
});
},
componentWillMount: function(){
this.setTime();
},
componentDidMount: function(){
window.setInterval(function () {
this.setTime();
}.bind(this), 1000);
},
render: function() {
return(
<div className="city-row" ref="cityRow">
<span className="city-time">{this.state.hours}:{this.state.minutes}:{this.state.seconds}</span>
</div>
)
}
});
Upvotes: 13