0%

javascript-always-use-arrow-function-in-setTimeout

A question from stackoverflow

The following code does not work, do you know why? When you run the code, you will got the error TypeError: Cannot read properties of undefined (reading 'navigate').

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import {Component, OnInit} from '@angular/core';
import {Router, RouterOutlet} from '@angular/router';
import {TestComponent} from "./test/test.component";

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, TestComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent implements OnInit {
title = 'angular-18';

constructor(private router: Router) {
}

gotoProduct() {
this.router.navigate(['product']);
}

ngOnInit() {
setTimeout(this.gotoProduct, 1000);
}
}

Reason:
Code executed by setTimeout() is called from an execution context separate from the function from which setTimeout was called. The usual rules for setting the this keyword for the called function apply, and if you have not set this in the call or with bind, it will default to the window (or global) object, even in strict mode. It will not be the same as the this value for the function that called setTimeout. - From MDN- The this problem for setTimeout

That means router is undefined in gotoProduct function. The reason is that this in gotoProduct function is not the instance of AppComponent. It is the instance of Window object.

How to fix it?

Use Arrow function

Arrow function doesn’t have its own this binding, it will inherit the this from the parent scope. So, you can use arrow function in setTimeout function to keep the context of the parent scope.

1
2
3
setTimeout(() => {
this.gotoProduct();
}, 1000);

Use bind

You can also use bind function to bind the this to the gotoProduct function.

1
setTimeout(this.gotoProduct.bind(this), 1000);

Conclusion

Becareful when using setTimeout function in Angular.
Always use arrow function in setTimeout function to keep the context of the parent scope.