Reputation: 5888
Trying to follow a simple clock/countdown tutorial in React:
constructor(props) {
super(props);
this.state = {
secondsRemaining: 10
};
}
componentDidMount(){
let interval = setInterval(this.timer, 1000);
this.setState({ secondsRemaining: this.state.secondsRemaining })
this.setState({ interval: interval });
};
componentWillUnmount() {
clearInterval(this.state.interval);
};
timer(){
this.setState({ secondsRemaining: this.state.secondsRemaining -1 });
};
Very obvious what everything does but when I run it, I get an error saying cannot read property secondsRemaining of undefined
in the timer function
It is probably something stupid I have missed out but I just cannot see it
followed the answer to this question: setInterval in a React app
Upvotes: 0
Views: 842
Reputation: 11
Because of your bounding context. You can use an arrow function or this.timer.bind(this)
Upvotes: 0
Reputation: 15632
Define timer
as an Arrow Function.
timer() => this.setState({ secondsRemaining: this.state.secondsRemaining -1 })
OR
.bind
your method inside constructor
:
constructor(props) {
super(props);
this.state = {
secondsRemaining: 10
};
this.timer = this.timer.bind(this);
}
I don't recommend this.timer.bind(this)
inside render
; because doing that, .bind
will create a new function on every render.
Upvotes: 0
Reputation: 3190
The myfunction.bind()
method specifies what this
will be refering to inside the method when its being called. To be sure that when you call this.timer() you are actually refering to your components state and not the object thats invoking it you will have to pass this.timer.bind(this)
.
Upvotes: 1
Reputation: 181
Because setInterval will call this.timer and this will be window object. you can use closure:
componentDidMount(){
let currentInstance = this;
let interval = setInterval(function(){ currentInstance.timer(); }, 1000);
...
};
at the moment of executing method componentDidMount it context with initialized property state, save into variable currentInstance. Then we closure value of currentInstance into setInterval first argument.
Upvotes: 0