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.setState, 500, {position: 1});
Enter setTimeout
It seems people don't realise that setTimeout and setInterval actually accept optional unlimited parameters.
setTimeout(callback, timeout?, param1?, param2?, ...)
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)
Isn't that beautiful and elegant? 😉
Bug?
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 for later call
// call later
const x = a() // error "a is not a function"
const y = b() // invokes doSomething and assigns a result
And in your case with setState, this 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() {/* */}
const a = 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.doSomething, 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.doSomething(), 500)
- wrap in a standard anonymous function, but since it comes with it's own
this, you must bind it to the this of the parent.
note that this wraps your function in another function AND THEN binds it, which creates yet another function. That is two additional functions every time you call it.
setTimeout(function(){this.doSomething()}.bind(this), 500)
foo(bar())thenbaris executed first and its return value is passed tofoo.foo()here is exactly to executebarafter desired timeout. Or am I completely wrong and it executes right away, and only return value after the desired time?bar, not call it and pass its returns value. Did you expect the behavior offoo(bar())to change, depending whatfoois doing? That would be really strange.