Reputation: 579
I'm trying to understand how to use setInterval or similar in Meteor with React for a timer. I have a child component that has an hourly start and end time, and uses moment.js to get the current time. If the current time is between the start and end time, I show a progress bar.
I'm using the react-timer-mixin, and right now my component looks like this.
Driver = React.createClass({
mixins: [TimerMixin],
componentDidMount: function(){
// componentDidMount is called by react when the component
// has been rendered on the page. We can set the interval here:
this.setInterval(this.currentTime, 15000);
},
currentTime: function() {
// Get the start time.
var beginTime = moment(this.props.driver.startTime,"hh:mm");
// Add an hour for end time.
var endTime = moment(beginTime).add(1,'hours');
// Get the current time.
var now = moment();
// Get total minutes between start and end.
totalMin = endTime.diff(beginTime);
// Get elapsed minutes.
currMin = now.diff(beginTime);
// Determine where we are in the schedule.
if (moment(now).isBetween(beginTime, endTime)) {
progress = Math.round((currMin / totalMin) * 60, -1);
console.log(progress);
return progress;
}
else {
// Show this schedule as done.
return 60
}
},
// A bunch of other functions
render() {
return (
<DriverBar current={this.currentTime()} total="60" />
);
}
});
I'm certain the currentTime function is running within setInterval, because progress is updated every 15 seconds in the browser console log, since I have that in my function at the moment. However, I cannot get the updated progress value in my component. It shows the initial progress value, but doesn't update with setInterval. Am I just calling the wrong thing in the <DriverBar />
?
Also, if this is not the React or Meteor way to do this, by all means I am not stuck to it and would appreciate direction.
Upvotes: 4
Views: 771
Reputation: 579
The answer for this type of scenario is to use state. Many thanks to Ramsay Lanier for the help.
Driver = React.createClass({
mixins: [TimerMixin],
getInitialState: function() {
return {progress: 0};
},
componentDidMount() {
this.setInterval(this.currentTime, 1000);
},
currentTime: function() {
[...]
if (moment(now).isBetween(beginTime, endTime)) {
progress = Math.round((currMin / totalMin) * 60, -1);
this.setState({progress: progress});
}
},
render() {
let progress = this.state.progress;
return (
<DriverBar current={progress} total="60" />
);
}
Upvotes: 0
Reputation: 21364
I'm fairly certain that this is an issue with this
. What this
refers to can change depending on the context in which a function is called, and this is a common pitfall with setTimer
. The typical solution is to use the javascript function bind
to explicitly set the this
context for the callback.
Try this:
this.setInterval(this.currentTime.bind(this), 15000);
Upvotes: 1