admin管理员组文章数量:1415684
Forgive me if this seems overly simple...this is the first thing I have ever made in React so I'm just trying to wrap my head around things. I'm already realizing I should have smaller ponent like buttons and render them with props and all that (goal is to refactor later!) but currently I am having a hard time figuring out how to use the setInterval method to change the state, and then stop that.
I'm building a pomodoro timer, and the general idea is that my state is maintaining the total seconds that the timer should have left. I have another function that will convert the total seconds into a time format I want to display.
My struggle is within my startStop() method, I would like the change the state of the running (the timer is running) to t/f and that will work, but I am clearly doing something wring with the setInterval. I want to set an interval (when there is time remaining) to change the state every second to be 1 second less. When I click the button again, the interval timer would stop and the current "state" of seconds remaining would be the same, so if you clicked the button again it would just start the timer again.
Thanks for the help! (This is all getting rendered from the create-react-app so there is more at my github is needed: )
import React, { Component } from "react ";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
sessionTimeEntry: 25, //in min
breakTimeEntry: 5, //in min
sessionRemainingSeconds: 1500, //in seconds
breakRemainingSeconds: 300, //in seconds
running: false,
timerLabel: "Session"
}
this.addSession = this.addSession.bind(this);
this.subSession = this.subSession.bind(this);
this.addBreak = this.addBreak.bind(this);
this.subBreak = this.subBreak.bind(this);
this.startStop = this.startStop.bind(this);
this.resetTimer = this.resetTimer.bind(this);
this.formatMinutes = this.formatMinutes.bind(this);
}
addSession() { //adding and subtracting methods need to also chage the session remaining in seconds to mirrow the entry time if ever changed
this.setState({
sessionTimeEntry: this.state.sessionTimeEntry + 1,
sessionRemainingSeconds: this.state.sessionRemainingSeconds + 60
})
}
subSession() {
this.setState({
sessionTimeEntry: this.state.sessionTimeEntry - 1,
sessionRemainingSeconds: this.state.sessionRemainingSeconds - 60
})
}
addBreak() {
this.setState({
breakTimeEntry: this.state.breakTimeEntry + 1,
breakRemainingSeconds: this.state.breakRemainingSeconds + 60
})
}
subBreak() {
this.setState({
breakTimeEntry: this.state.breakTimeEntry - 1,
breakRemainingSeconds: this.state.breakRemainingSeconds - 60
})
}
startStop() {
let timer;
const status = this.state.running;
switch (status) {
case false:
console.log("should start!")
this.setState({
running: true
})
while (this.state.breakRemainingSeconds > 0) {
timer = setInterval(() => {
this.setState({
breakRemainingSeconds: this.state.breakRemainingSeconds - 1
});
console.log(this.state.breakRemainingSeconds);
}, 1000)
}
break;
case true:
console.log("should stop")
this.setState({
running: false
})
clearInterval(timer)
break;
default:
break;
}
}
resetTimer() {
this.setState({
sessionTimeEntry: 25,
breakTimeEntry: 5,
sessionRemainingSeconds: 1500,
breakRemainingSeconds: 300,
running: false,
timerLabel: "Session"
})
}
formatMinutes(time) {
let seconds = time;
const minutes = (seconds % 60 === 0) ? ((seconds / 60) < 10 ? "0" + seconds / 60 : seconds / 60) : (Math.floor(seconds / 60) < 10 ? "0" + Math.floor(seconds / 60) : Math.floor(seconds / 60));
seconds = (seconds % 60 === 0) ? "00" : ((seconds % 60 < 10) ? "0" + (seconds % 60) : seconds % 60)
console.log(minutes + ":" + seconds);
return minutes + ":" + seconds;
}
render() {
return ( <
div >
<
h1 > Pomodoro Clock < /h1> <
h2 > {
this.state.sessionTimeEntry
} < /h2> <
div id = 'timerContainer' >
<
h3 id = "session-label" > Session Time < /h3> <
h3 id = "session-length" > {
this.formatMinutes(this.state.sessionRemainingSeconds)
} < /h3> <
button onClick = {
this.addSession
}
id = "session-increment" > ^ < /button> <
button onClick = {
this.subSession
}
id = "session-decrement" > v < /button> <
/div> <
div id = 'timerContainer' >
<
h3 id = "break-label" > Break Time < /h3> <
h3 id = "break-length" > {
this.state.breakTimeEntry
} < /h3> <
button onClick = {
this.addBreak
}
id = "break-increment" > ^ < /button> <
button onClick = {
this.subBreak
}
id = "break-decrement" > v < /button> <
/div> <
div >
<
button onClick = {
this.startStop
}
id = "start-stop" > Start / Stop < /button> <
button onClick = {
this.resetTimer
}
id = "reset" > Reset < /button> <
/div> <
/div>
)
}
}
export default App;
**************** UPDATE *****************
Figured it all out! Here is a link to the working codepen to see it in action.
Forgive me if this seems overly simple...this is the first thing I have ever made in React so I'm just trying to wrap my head around things. I'm already realizing I should have smaller ponent like buttons and render them with props and all that (goal is to refactor later!) but currently I am having a hard time figuring out how to use the setInterval method to change the state, and then stop that.
I'm building a pomodoro timer, and the general idea is that my state is maintaining the total seconds that the timer should have left. I have another function that will convert the total seconds into a time format I want to display.
My struggle is within my startStop() method, I would like the change the state of the running (the timer is running) to t/f and that will work, but I am clearly doing something wring with the setInterval. I want to set an interval (when there is time remaining) to change the state every second to be 1 second less. When I click the button again, the interval timer would stop and the current "state" of seconds remaining would be the same, so if you clicked the button again it would just start the timer again.
Thanks for the help! (This is all getting rendered from the create-react-app so there is more at my github is needed: https://github./ryanmdoyle/web-pomodoro)
import React, { Component } from "react ";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
sessionTimeEntry: 25, //in min
breakTimeEntry: 5, //in min
sessionRemainingSeconds: 1500, //in seconds
breakRemainingSeconds: 300, //in seconds
running: false,
timerLabel: "Session"
}
this.addSession = this.addSession.bind(this);
this.subSession = this.subSession.bind(this);
this.addBreak = this.addBreak.bind(this);
this.subBreak = this.subBreak.bind(this);
this.startStop = this.startStop.bind(this);
this.resetTimer = this.resetTimer.bind(this);
this.formatMinutes = this.formatMinutes.bind(this);
}
addSession() { //adding and subtracting methods need to also chage the session remaining in seconds to mirrow the entry time if ever changed
this.setState({
sessionTimeEntry: this.state.sessionTimeEntry + 1,
sessionRemainingSeconds: this.state.sessionRemainingSeconds + 60
})
}
subSession() {
this.setState({
sessionTimeEntry: this.state.sessionTimeEntry - 1,
sessionRemainingSeconds: this.state.sessionRemainingSeconds - 60
})
}
addBreak() {
this.setState({
breakTimeEntry: this.state.breakTimeEntry + 1,
breakRemainingSeconds: this.state.breakRemainingSeconds + 60
})
}
subBreak() {
this.setState({
breakTimeEntry: this.state.breakTimeEntry - 1,
breakRemainingSeconds: this.state.breakRemainingSeconds - 60
})
}
startStop() {
let timer;
const status = this.state.running;
switch (status) {
case false:
console.log("should start!")
this.setState({
running: true
})
while (this.state.breakRemainingSeconds > 0) {
timer = setInterval(() => {
this.setState({
breakRemainingSeconds: this.state.breakRemainingSeconds - 1
});
console.log(this.state.breakRemainingSeconds);
}, 1000)
}
break;
case true:
console.log("should stop")
this.setState({
running: false
})
clearInterval(timer)
break;
default:
break;
}
}
resetTimer() {
this.setState({
sessionTimeEntry: 25,
breakTimeEntry: 5,
sessionRemainingSeconds: 1500,
breakRemainingSeconds: 300,
running: false,
timerLabel: "Session"
})
}
formatMinutes(time) {
let seconds = time;
const minutes = (seconds % 60 === 0) ? ((seconds / 60) < 10 ? "0" + seconds / 60 : seconds / 60) : (Math.floor(seconds / 60) < 10 ? "0" + Math.floor(seconds / 60) : Math.floor(seconds / 60));
seconds = (seconds % 60 === 0) ? "00" : ((seconds % 60 < 10) ? "0" + (seconds % 60) : seconds % 60)
console.log(minutes + ":" + seconds);
return minutes + ":" + seconds;
}
render() {
return ( <
div >
<
h1 > Pomodoro Clock < /h1> <
h2 > {
this.state.sessionTimeEntry
} < /h2> <
div id = 'timerContainer' >
<
h3 id = "session-label" > Session Time < /h3> <
h3 id = "session-length" > {
this.formatMinutes(this.state.sessionRemainingSeconds)
} < /h3> <
button onClick = {
this.addSession
}
id = "session-increment" > ^ < /button> <
button onClick = {
this.subSession
}
id = "session-decrement" > v < /button> <
/div> <
div id = 'timerContainer' >
<
h3 id = "break-label" > Break Time < /h3> <
h3 id = "break-length" > {
this.state.breakTimeEntry
} < /h3> <
button onClick = {
this.addBreak
}
id = "break-increment" > ^ < /button> <
button onClick = {
this.subBreak
}
id = "break-decrement" > v < /button> <
/div> <
div >
<
button onClick = {
this.startStop
}
id = "start-stop" > Start / Stop < /button> <
button onClick = {
this.resetTimer
}
id = "reset" > Reset < /button> <
/div> <
/div>
)
}
}
export default App;
**************** UPDATE *****************
Figured it all out! Here is a link to the working codepen to see it in action.
https://codepen.io/ryanmdoyle/pen/vaxoaG
Share Improve this question edited Jul 24, 2018 at 20:12 Ryan asked Jul 22, 2018 at 20:46 RyanRyan 792 silver badges10 bronze badges3 Answers
Reset to default 2I think problem is in your startStop function. Please remove while loop from your function.
startStop() {
const status = this.state.running;
switch (status) {
case false:
console.log("should start!")
this.setState({
running: true
})
this.timer = setInterval(() => {
this.setState({
breakRemainingSeconds: this.state.breakRemainingSeconds - 1
});
console.log(this.state.breakRemainingSeconds);
}, 1000)
}
break;
case true:
console.log("should stop")
this.setState({
running: false
})
clearInterval(this.timer)
break;
default:
break;
}
}
You could create a setInterval
that decreases breakRemainingSeconds
with one every second, and store the id returned by setInterval
on the instance. You can later use clearInterval(this.timer)
when you want to stop the timer.
startStop() {
const { running } = this.state;
if (running) {
this.setState({
running: false
});
clearInterval(this.timer);
} else {
this.setState({
running: true
});
this.timer = setInterval(() => {
this.setState(previousState => {
return {
breakRemainingSeconds: previousState.breakRemainingSeconds - 1
};
});
}, 1000);
}
}
I suggest using a library like moment
. Just install it as a dependency: npm i react-moment because JS can be a little bit tricky with dates and time. Anyways, here's a function that can get you started. I hope it helps. I used your breakRemainingSeconds
for demonstration, but you can tweak it to achieve all the 'time' management you also may need in your ponent.
class Timer extends React.Component {
constructor() {
super();
this.state = {
time: {},
breakRemainingSeconds: 300
};
this.timer = 0;
this.startTimer = this.startTimer.bind(this);
this.countDown = this.countDown.bind(this);
}
// Let's make some sense of JS date and time It can get a little bit tricky sometimes.
// So, what we're doing here is taking the values and converting it in hours minutes, seconds.
// In the example below we are using minutes and seconds, but just in case we got hours in there too :)
createTime(secs){
let hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
let minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
let seconds = Math.ceil(divisor_for_seconds);
let timeObject = {
"h": hours,
"m": minutes,
"s": seconds
};
return timeObject;
}
ponentDidMount() {
// Taking the starting point -> breakRemainingSeconds <-
// Passing it as the parameter and setting the state's time object to it.
let timeLeft = this.createTime(this.state.breakRemainingSeconds);
this.setState({ time: timeLeft });
}
// Check the current state and potentially (if != 0) start our main function
startTimer() {
if (this.timer == 0) {
this.timer = setInterval(this.countDown, 1000);
}
}
countDown() {
// Remove one second, set state so a re-render happens.
let seconds = this.state.breakRemainingSeconds - 1;
this.setState({
time: this.createTime(seconds),
breakRemainingSeconds: seconds
});
// Check if we're at zero, and if so, clear the Interval
if (seconds == 0) {
clearInterval(this.timer);
}
}
render() {
return(
<div>
<button
onClick={this.startTimer} style={{marginRight:'12px'}}>Let's Go</button>
m: {this.state.time.m} s: {this.state.time.s}
</div>
);
}
}
ReactDOM.render(<Timer/>, document.getElementById('container'));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
I put a button
here to start the process, but if you want to start it once the ponent renders, just put this.startTimer();
inside of the ponentDidMount
lifecycle
本文标签: javascriptCreating a timer in reactStack Overflow
版权声明:本文标题:javascript - Creating a timer in react - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745218522a2648283.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论