In my NextJS/React typescript app I'm using a setTimeout.
There is a bug in React apps causing setTimeout's to get called instantly, which I then found a fix in this answer here: ReactJS: setTimeout() not working?
Below is my code, but I'm getting the following typescript error on the this
on this.resetNotification
any 'this' implicitly has type 'any' because it does not have a type annotation.ts(2683) Board.tsx(158, 7): An outer value of 'this' is shadowed by this container.
@bind
resetNotification(): any {
console.log('resetNotification...');
this.setState({ notificationClass: 'spin-in-notification' });
this.props.setNotification('', false);
}
@bind
private handleNotificationClick() {
this.setState({ notificationClass: 'slide-out-bck-top' });
setTimeout(
function() {
this.resetNotification();
}
.bind(this),
500
);
}
In my NextJS/React typescript app I'm using a setTimeout.
There is a bug in React apps causing setTimeout's to get called instantly, which I then found a fix in this answer here: ReactJS: setTimeout() not working?
Below is my code, but I'm getting the following typescript error on the this
on this.resetNotification
any 'this' implicitly has type 'any' because it does not have a type annotation.ts(2683) Board.tsx(158, 7): An outer value of 'this' is shadowed by this container.
@bind
resetNotification(): any {
console.log('resetNotification...');
this.setState({ notificationClass: 'spin-in-notification' });
this.props.setNotification('', false);
}
@bind
private handleNotificationClick() {
this.setState({ notificationClass: 'slide-out-bck-top' });
setTimeout(
function() {
this.resetNotification();
}
.bind(this),
500
);
}
Share
Improve this question
asked Mar 13, 2019 at 22:34
Leon GabanLeon Gaban
39k122 gold badges348 silver badges550 bronze badges
3 Answers
Reset to default 10Do it with arrow function on setTimeout for heredate parents props
setTimeout(
() => {
this.resetNotification();
}......
If you still want to use function () {}
syntax, you can pass this
as the first parameter to the function, along with a type annotation. Like this:
setTimeout(
function(this: Board) {
this.resetNotification();
}
.bind(this),
500
);
I'm assuming since the file is called Board.tsx
that your ponent is <Board>
. If not, change the type annotation for this
.
Just pass the function as a reference, no need to wrap it in an anonymous function or even bind it, which creates yet another function.
setTimeout(this.resetNotification, 500);
There is no bug in React calling setTimeout instantly, so if you were puzzled by it, consider this.
function doSomething() {/* */}
const a = doSomething() // immediately invokes and assigns a result
const b = doSomething // stores a reference
// call later
const x = a() // error
const y = b() // invokes doSomething and assigns a result
And in your case, the "bug" you mention is basically the same thing.
When you register your setTimeout
callback, you mistakenly immediately call it, where instead you should pass a reference to it.
function doSomething() {/* */}
// wrong
setTimeout(doSomething(), 500) // This is basically the same as writing the `a` from above
setTimeout(a, 500) // like this. See the problem? a() cannot be called later.
To fix it, you have three options.
- pass a reference
setTimeout(this.resetNotification, 500)
- wrap in an anonymous arrow function which is transparent to
this
,
meaning it captures the outer (parent)this
.
note that this wraps your function in another function every time you call this
setTimeout(() => this.resetNotification(), 500)
- wrap in a standard anonymous function, but since it es with it's own
this
, you must bind it to thethis
of the parent.
note that this wraps your function in another function AND THEN binds it, which creates a third function every time
setTimeout(function(){this.resetNotification()}.bind(this), 500)
Enter setTimeout
setTimeout(callback, timeout?, param1?, param2?, ...)
It seems people don't realise that setTimeout
and setInterval
actually accept optional unlimited parameters. The reason is to make calling the callback simpler, so instead of this
setTimeout(
function(){
this.doSomething(true, "string", someVariable)
}.bind(this),
500
)
You can write this
setTimeout(this.doSomething, 500, true, "string", someVariable)