React setInterval with update state makes onClick not working - javascript

I made a custom audio player in React that updates the so called "Scrubber" of the audio file (progressbar) with the value based on duration of the player. Everything works fine except that if you press the play/pause button when the interval updates (mousedown -> interval updates state -> mouseup) then the button click doesn't fire.
import React, { Component } from 'react';
import ReactSVG from 'react-svg';
import VolumeButton from 'components/VolumeButton/VolumeButton.jsx';
import play from 'img/icons/play.svg';
import pause from 'img/icons/pause.svg';
import './AudioPlayer.css';
class AudioPlayer extends Component {
constructor(props) {
super(props);
this.state = {
currentTime: '00:00',
endTime: '00:00',
intervalsInitiated: false,
player: null,
playing: false,
progressBar: null
};
this.handleResize = this.handleResize.bind(this);
}
initIntervals = () => {
let intervals = setInterval(() => {
this.updateScrubber(this.state.player.currentTime);
this.updateTime(this.state.player.currentTime);
}, 100);
this.setState({
intervals: intervals,
intervalsInitiated: true
});
};
setUpAudioTime = player => {
console.log('setup time');
let playerCurrentTime = player.currentTime;
let currentTime = this.calculateTime(playerCurrentTime);
this.setState({
currentTime: currentTime,
endTime: this.calculateTime(player.duration)
});
this.updateScrubber(playerCurrentTime);
};
initPlayer = () => {
console.log('initPlayer');
// Add resize listener for showing volume on desktop
this.addResize();
this.handleResize();
// Setup correct player
let player = new Audio(this.props.audioPath);
let progressBar = document.querySelector('.ProgressBar');
// Add event for audio stopped for play button
player.addEventListener('ended', () => this.toggleAudioPlay());
// Set state to correct player
// TODO: Do this in update aswell going from one to another
this.setState({
player: player,
progressBar: progressBar
});
player.addEventListener('loadedmetadata', () =>
this.setUpAudioTime(player)
);
};
toggleAudioPlay = () => {
console.log('toggling audio');
if (!this.state.player) {
return;
}
!this.state.intervalsInitiated
? this.initIntervals()
: this.resetComponent();
this.state.playing
? this.state.player.pause()
: this.state.player.play();
this.setState({
playing: !this.state.playing
});
};
updateScrubber = playerCurrentTime => {
if (!this.state.player || !this.state.progressBar) {
return;
}
let prog = this.state.progressBar;
prog.value = playerCurrentTime / this.state.player.duration;
this.setState({
progressBar: prog
});
};
updateTime = playerCurrentTime => {
this.setState({
currentTime: this.calculateTime(playerCurrentTime)
});
};
calculateTime = lengthInSeconds => {
let minutes = Math.floor(lengthInSeconds / 60);
let seconds = Math.floor(lengthInSeconds) - minutes * 60;
let time =
(minutes < 10 ? '0' + minutes : minutes) +
':' +
(seconds < 10 ? '0' + seconds : seconds);
return time;
};
seek = event => {
if (!this.state.player || !this.state.progressBar) {
return;
}
let percent =
event.nativeEvent.offsetX / this.state.progressBar.offsetWidth;
let prog = this.state.progressBar;
prog.value = percent;
this.setState({ progressBar: prog });
let newTime = percent * this.state.player.duration;
let player = this.state.player;
player.currentTime = newTime;
this.setState({
player: player
});
this.updateTime(newTime);
};
resetComponent() {
console.log('reset component');
clearInterval(this.state.intervals);
this.setState({
intervalsInitiated: false
});
}
componentDidMount() {
this.initPlayer();
}
render() {
return (
<div
className={`AudioPlayer ${
this.state.width < 800 ? 'AudioPlayer--extended' : ''
}`}
>
<audio className="MarkerAudio" preload="metadata">
<source src={this.props.audioPath} type="audio/mp3" />
Your device doesnt support audio format.
</audio>
<div className="PlayerControls">
<div className="PlayButton" onClick={this.toggleAudioPlay}>
{this.state.playing ? (
<ReactSVG
className="AudioIcon"
svgStyle={{ height: '100%', width: '100%' }}
path={pause}
/>
) : (
<ReactSVG
className="AudioIcon"
svgStyle={{
height: '100%',
left: '2px',
position: 'relative',
width: '100%'
}}
path={play}
/>
)}
</div>
<span className="CurrentTime">
{this.state.currentTime}
</span>
<progress
onClick={this.seek}
className="ProgressBar"
value="0"
min="0"
max="1"
/>
<span>{this.state.endTime}</span>
</div>
</div>
);
}
}
export default AudioPlayer;
However, the click still works if I make sure I do a "fast-click" or if the interval isn't initiated. Any ideas on how to handle this? Should I use a onMouseDown or something instead? Or is there anyway to make sure that the interval and state change doesn't interfere with the onClick?

So for anyone wondering it had something do to with click on the icon not bubbling properly when state updated. All I had to do to fix this was to add pointer-events: none; on the icon so the click gets triggered directly on the div and not on icon.

Related

Full Calendar Callbacks

I am working with Full Calendar with React.
This is my code
<FullCalendar
ref={calendarRef}
editable={true}
headerToolbar={{ start: '', center: '', end: '' }}
plugins={[timeGridPlugin, interaction]}
initialView="timeGridWeek"
selectable={true}
select={onDateSelect}
eventDrop={onEventDrop}
eventResize={onEventResize}
eventContent={(args) => renderEventContent(args)}
allDaySlot={false}
events={events}
/>
And I have 2 callbacks eventDrop and eventResize
const onEventDrop = (event) => {
const slot = { ...event.event._def.extendedProps };
const delta = event.delta;
slot.date = new Date(slot.date);
slot.date.setHours(0, 0, 0, 0)
slot.date.setDate(slot.date.getDate() + delta.days)
slot.startTime += (delta.milliseconds / 1000)
slot.endTime += (delta.milliseconds / 1000)
updateSlot(id, slot.id, slot).then(() => {
loadSlots()
}).catch(() => {
event.revert()
})
}
const onEventResize = (event) => {
const slot = { ...event.event._def.extendedProps };
slot.startTime += (event.startDelta.milliseconds / 1000)
slot.endTime += (event.endDelta.milliseconds / 1000)
updateSlot(id, slot.id, slot).then(() => {
loadSlots()
}).catch(() => {
event.revert()
})
}
for some reason the events aren't called always, the event itself gets dragger and resized and its reflected to the view
But the callback isn't triggered
I couldn't find the exact time when its not called, but it works sometimes then it stops
I tried a different event and it works, then it stops, its mostly random
Is there any reported bug about this issue, or do I have an issue in the code?
Regards,

Task to do StopWatch on RxJs using Observables

I have a task to do StopWatch. I did it using Subject, but I should do it via Observables.
I read about at rxjs.dev. But I can`t understand it. Help me plz
The stopwatch must have the following buttons:
"Start / Stop" - start / stop timing, stops and resets the stopwatch value.
"Wait" - works on a double click (the time between clicks is not more than 300 ms!) The stopwatch should stop timing; if you press start after it, then the countdown is resumed.
"Reset" - reset the stopwatch to 0. Resets the stopwatch and starts counting again.
import "./App.css";
import { useEffect, useState } from "react";
import { interval, Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
function App() {
const [time, setTime] = useState(0);
const [status, setStatus] = useState(false);
useEffect(() => {
const unsubscribe$ = new Subject();
interval(10)
.pipe(takeUntil(unsubscribe$))
.subscribe(() => {
if (status === true) {
setTime(val => val + 10);
}
});
return () => {
unsubscribe$.next();
unsubscribe$.complete();
};
}, [status]);
const start = React.useCallback(() => {
setStatus(true);
}, []);
const stop = React.useCallback(() => {
setStatus(false);
}, []);
const reset = React.useCallback(() => {
setTime(0);
setStatus(false);
}, []);
console.log(time);
return (
<div className="App">
<h1>Секундомер</h1>
<span>{Math.floor(time / (1000 * 60 * 60)) % 24}</span>
<span>{Math.floor((time / (1000 * 60)) % 60)}</span>
<span>{Math.floor((time / 1000) % 60)}</span>
<div>
<button onClick={()=> start()} class="start">Старт</button>
<button onClick={()=> stop()}class="stop">Стоп</button>
<button onClick={()=> reset()} class="reset">Перезапуск</button>
</div>
</div>
);
}
export default App;```
I created a pretty generic stopwatch implementation a while back.
type StopwatchAction = "START" | "STOP" | "RESET" | "END";
function createStopwatch(
control$: Observable<StopwatchAction>,
interval = 1000
): Observable<number>{
return defer(() => {
let toggle: boolean = false;
let count: number = 0;
const ticker = timer(0, interval).pipe(
map(x => count++)
);
const end$ = of("END");
return concat(
control$,
end$
).pipe(
catchError(_ => end$),
switchMap(control => {
if(control === "START" && !toggle){
toggle = true;
return ticker;
}else if(control === "STOP" && toggle){
toggle = false;
return EMPTY;
}else if(control === "RESET"){
count = 0;
if(toggle){
return ticker;
}
}
return EMPTY;
})
);
});
}
Using this is just a matter of hooking the correct events into a stream of StopwatchActions. This example only sends "START" and "RESET" based on button clicks, but you can merge in "STOP" and "END" as well.
For example:
createStopwatch(merge(
fromEvent(startBtn, 'click').pipe(mapTo("START")),
fromEvent(resetBtn, 'click').pipe(mapTo("RESET"))
)).subscribe(seconds => {
secondsField.innerHTML = seconds % 60;
minuitesField.innerHTML = Math.floor(seconds / 60) % 60;
hoursField.innerHTML = Math.floor(seconds / 3600);
});

React: How to force a function to run after another one is totally completed?

In this React Pomodoro Clock, there is a function countDown. In it there is a function called three. Currently, when this.setState({ init: 'break' }); is set in two, three occurs immediately. However, three should wait until two completes. Any help would be greatly appreciated.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
/*
* A simple React component
*/
const initState = {
breakLength: 5,
breakSeconds: undefined,
sessionLength: 25,
sessionSeconds: undefined,
init: 'session',
timeLeft: undefined,
timeLeftSeconds: undefined,
started: false,
intervalFunc: undefined
}
const secondsToMins = (time) => {
//let converted = Math.floor(time / 60) + ':' + ('0' + Math.floor(time % 60)).slice(-2);
let converted = ('0' + Math.floor(time / 60)).slice(-2) + ':' + ('0' + Math.floor(time % 60)).slice(-2);
//console.log('converted')
//console.log(converted)
//console.log('#######')
return converted;
}
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = initState;
this.breakDecrement = this.breakDecrement.bind(this);
this.breakIncrement = this.breakIncrement.bind(this);
this.sessionDecrement = this.sessionDecrement.bind(this);
this.sessionIncrement = this.sessionIncrement.bind(this);
this.startStop = this.startStop.bind(this);
this.reset = this.reset.bind(this);
}
componentDidMount() {
// seconds are used for the countDown()
// seconds are converted to MM:SS at every t-minus
let breakSeconds = this.state.breakLength * 60;
let sessionSeconds = this.state.sessionLength * 60;
// Initialize everything
this.setState({ breakSeconds: breakSeconds });
this.setState({ sessionSeconds: sessionSeconds });
this.setState({ timeLeftSeconds: sessionSeconds });
this.setState({ timeLeft: secondsToMins(sessionSeconds) });
}
breakDecrement() {
// decrements the breakLength and the breakSeconds
// breakLength is only a number ie. 5 (does not show seconds)
// breakSeconds is that nunber converted into seconds
let breakLength = this.state.breakLength - 1;
if (breakLength > 0 && breakLength < 61){
this.setState({ breakLength: breakLength });
let breakSeconds = breakLength * 60;
this.setState({ breakSeconds: breakSeconds });
}
}
breakIncrement() {
// same as decrement except does increment
let breakLength = this.state.breakLength + 1;
if (breakLength > 0 && breakLength < 61){
this.setState({ breakLength: breakLength });
let breakSeconds = breakLength * 60;
this.setState({ breakSeconds: breakSeconds });
}
}
sessionDecrement() {
// decrements the sessionLength and the sessionSeconds
// sessionLength is only a number ie. 25 (does not show seconds)
// sessionSeconds is that nunber converted into seconds
let sessionLength = this.state.sessionLength - 1;
if (sessionLength > 0 && sessionLength < 61){
this.setState(prevState => ({
sessionLength: prevState.sessionLength-1,
sessionSeconds: (prevState.sessionLength-1)*60,
timeLeftSeconds: (prevState.sessionLength-1)*60,
timeLeft: secondsToMins((prevState.sessionLength-1)*60)})
);
}
}
sessionIncrement() {
// same as decrement except does increment
let sessionLength = this.state.sessionLength + 1;
if (sessionLength > 0 && sessionLength < 61){
this.setState(prevState => ({
sessionLength: prevState.sessionLength+1,
sessionSeconds: (prevState.sessionLength+1)*60,
timeLeftSeconds: (prevState.sessionLength+1)*60,
timeLeft: secondsToMins((prevState.sessionLength+1)*60)})
);
}
}
startStop(id) {
// starts the countDown, which runs continuously until the start/stop button
// is pressed again, which pauses the countdown.
// the id parameter is used by countDown to play the audio beep
if(!this.state.started){
this.countDown(id);
this.setState({ started: true});
}
// pauses the countDown
if(this.state.started){
let intervalFunc = this.state.intervalFunc;
clearInterval(intervalFunc);
this.setState({ started: false});
}
}
reset() {
let intervalFunc = this.state.intervalFunc;
clearInterval(intervalFunc);
// reset state to default values
this.setState({ breakLength: 5 });
this.setState({ sessionLength: 25 });
this.setState({ init: 'session' });
this.setState({ timeLeftSeconds: 1500})
this.setState({ timeLeft: '25:00' });
}
countDown(id){
// set the function to a variable and set state to it, so the function
// can be paused with clearInterval()
var intervalFunc = setInterval(() => down(this.state.timeLeftSeconds--), 1000);
this.setState({intervalFunc: intervalFunc});
const down = (time) =>
{
const one = async () =>{
if(time > 0){
// converts seconds to MM:SS at every t-minus
this.setState({ timeLeft: secondsToMins(time)});
console.log(time);
console.log(this.state.timeLeft);
}
return;
}
//when time reaches 0 set state.init to break
// and set seconds left to break seconds
const two = async () => {
if(time == 0 && this.state.init == 'session'){
this.setState({ timeLeft: secondsToMins(time)});
let sound = document.getElementById(id).childNodes[0];
this.setState({ init: 'break' });
console.log(this.state.init)
sound.play();
this.setState({ timeLeftSeconds: this.state.breakSeconds});
}
return;
}
//when time reaches 0 set state.init to session
// and set seconds left to session seconds
const three = async () => {
if(time == 0 && this.state.init == 'break'){
this.setState({ timeLeft: secondsToMins(time)});
let sound = document.getElementById(id).childNodes[0];
this.setState({ init: 'session' });
console.log(this.state.init)
sound.play();
this.setState({ timeLeftSeconds: this.state.sessionSeconds});
}
return;
}
one().then(two).then(three);
}
}
render() {
return (
<div id="clock">
<h1 id="title">25-5 Clock</h1>
<div>
<p id="break-label">Break Length</p>
<p id="break-length">{this.state.breakLength}</p>
<button id="break-decrement" onClick={e => this.breakDecrement()}> Decrease </button>
<button id="break-increment" onClick={e => this.breakIncrement()}> Increase </button>
</div>
<div>
<p id="session-label">Session Length</p>
<p id="session-length">{this.state.sessionLength}</p>
<button id="session-decrement" onClick={e => this.sessionDecrement()}> Decrease </button>
<button id="session-increment" onClick={e => this.sessionIncrement()}> Increase </button>
</div>
<hr/>
<div>
<p id="timer-label">{this.state.init}</p>
<p id="time-left">{this.state.timeLeft}</p>
<button id="start_stop" onClick={e => this.startStop(e.target.id)}><audio id="beep" src='./beep.mp3'></audio> start/stop </button>
<button id="reset" onClick={e => this.reset()}> reset </button>
</div>
</div>
);
}
};
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Clock />, document.getElementById("app"));
index.html:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>25-5 Clock</title>
<style>
</style>
</head>
<body>
<main>
<div id="app"></app>
</main>
</body>
</html>
You need to make them asynchronous.
like...
const one = async () => {
//some code
return
}
const two = async () => {
//some code
return
}
const three = async () => {
//some code
return
}
Then you can...
one().then(two).then(three)
You can do that by making the functions return a Promise and using the async / await keywords to wait until they're finished before starting the next.
const setDelay = delay => new Promise(resolve => {
console.log(`Process running for ${delay}`);
setTimeout(() => {
console.log('Process done');
resolve();
}, delay);
});
(async () => {
await setDelay(2000);
await setDelay(3000);
await setDelay(1000);
})();
Or you could do without async / await and chain the promises.
const setDelay = delay => new Promise(resolve => {
console.log(`Process running for ${delay}`);
setTimeout(() => {
console.log('Process done');
resolve();
}, delay);
});
setDelay(3000)
.then(() => setDelay(1000))
.then(() => setDelay(4000));
Or just use good 'ol fashioned callbacks. But I'd go with one of the above.
The solution:
Use an array to hold states and duration:
const states = [ { name: 'session', duration: 1500 }, { name: 'break', duration: 300 } ]
Alternate the index of the array to alternate between session and break.
countDown(id){
// set the function to a variable and set state to it, so the function
// can be paused with clearInterval()
var intervalFunc = setInterval(() => down(this.state.timeLeftSeconds--), 1000);
this.setState({intervalFunc: intervalFunc});
const down = (time) =>
{
if(time > 0){
// converts seconds to MM:SS at every t-minus
this.setState({ timeLeft: secondsToMins(time)});
console.log(time);
console.log(this.state.timeLeft);
}
if (time <= 0) {
this.setState({ timeLeft: secondsToMins(time)});
let sound = document.getElementById(id).childNodes[0];
sound.play();
let stateIndex = (this.state.stateIndex + 1) % states.length;
this.setState({ stateIndex: stateIndex});
this.setState({ timeLeftSeconds: states[stateIndex].duration});
this.setState({ init: states[stateIndex].name});
console.log(this.state.init);
}
}
}

Soundcloud stream, soundmanager2 object never starts playing on Chrome when calling play()

Using SC.stream in my react app, I'm simply trying to play a track from soundcloud API. Here is my code:
SC.initialize({
client_id: '12xxx' // my client ID
});
//[...]
console.log(this.props.track.trackId); // I get here successfully the trackId from the song I'd like to play
SC.stream('/tracks/'+this.props.track.trackId, function(track){
track.play();
console.log(track); // I successfully get the track object here. playState attribute is on 1
});
Unfortunately, the tracks never starts playing. I get no errors in the console.
Edit: the problem is only on chrome, it works perfectly on firefox and safari. I'm even more puzzled now.
Edit 2: it seems to be linked to the HTML5 player not working on Chrome: when you re-enable flash player on chrome://plugins/ by checking "always allowed to run", it works
I am not sure from the code what "track" refers to when you have track.play(). If it is the audio div then this should help.
class PlayerCtrlRender extends React.Component {
render() {
let index = this.state.playIndex;
let currentTrack = this.state.randomOn ? this.state.shuffledQueue[index] : this.props.queue[index];
let source = 'http://192.168.0.101:3950/play/' + currentTrack.location;
let title = currentTrack.title;
let progressData = {count: this.state.progressCount * 100, index: this.state.progressIndex * 100};
return (
<div id='PlayerCtrlSty' style={PlayerCtrlSty}>
<div className='FlexBox'>
<div style={timerLeftSty}>{this.state.progressIndex}</div>
<PlayerActions playing={this.state.isPlaying} clickHandler={this.clickHandler}/>
<div style={timerRightSty}>{this.state.progressCount}</div>
</div>
<JProgressBar data={progressData} position='none' />
<div id="title" style={{textAlign: 'center'}}>{title}</div>
<audio
ref="audioDiv"
src={source}
onDurationChange={this.onDurationChange}
onTimeUpdate={this.onTimeUpdate}
onEnded={this.nextSong}
/>
</div>
);
}
}
export default class PlayerCtrl extends PlayerCtrlRender {
constructor() {
super();
this.state = {
playIndex: 0,
queueLength: 1,
isPlaying: false,
progressCount: 0,
progressIndex: 0,
shuffledQueue: [{title: '', location: ''}],
randomOn: false
};
}
componentDidMount = () => {
let queue = knuthShuffle(this.props.queue.slice(0));
this.setState({queueLength: queue.length, shuffledQueue: queue});
this.refs.audioDiv.volume = .1;
}
clickHandler = (buttonid) => {
this.refs.audioDiv.autoplay = false;
switch (buttonid) {
case 'play': this.refs.audioDiv.play(); this.setState({isPlaying: true}); break;
case 'pause': this.refs.audioDiv.pause(); this.setState({isPlaying: false}); break;
case 'back': this.refs.audioDiv.currentTime = 0; break;
case 'next': this.nextSong(); break;
case 'random': this.refs.audioDiv.autoplay = this.state.isPlaying;
this.setState({randomOn: !this.state.randomOn}); break;
}
}
nextSong = () => {
this.refs.audioDiv.autoplay = this.state.isPlaying;
this.refs.audioDiv.currentTime = 0;
let newIndex = this.state.playIndex + 1;
if (newIndex == this.state.queueLength) newIndex = 0;
this.setState({playIndex: newIndex});
}
onDurationChange = () => {
let duration = this.refs.audioDiv.duration;
duration = getTime(Math.floor(duration));
this.setState({progressCount: duration})
this.setState({progressIndex: 0})
}
onTimeUpdate = () => {
let currentTime = this.refs.audioDiv.currentTime;
currentTime = getTime(Math.floor(currentTime));
this.setState({progressIndex: currentTime})
}
}

React JS - Live clock update

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>
)
}
});
The official React Docs describe exactly what you need (and even explains why you should do it as described):
--> React Docs: State and Lifecycle
Example on CodePen:
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')
);
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>
)
}
});
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>;
}
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')
);
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') );
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.

Categories