@HostListener('click') で Error: Maximum call stack size exceeded が出たとき


やんごとない事情で、クリックしたらイベントを発火するシンプルな Angular コンポーネントを作ることになりました。それで、このように実装してみました。

@Component({
  selector: 'hello',
  template: `<h1>Hello!</h1>`,
})
export class HelloComponent  {
  @Output() click = new EventEmitter<void>();

  // This function causes Error: Maximum call stack size exceeded.
  // this.click.emit() calls onClick recursively.
  @HostListener('click')
  onClick (): void {
    this.click.emit();
  }
}

ざっと動作させてちゃんと動いてるねー。と思ってよく見たら、コンソールに不穏なエラーが。

ERROR RangeError: Maximum call stack size exceeded

とのことです。どうやらこの書き方をすると無限ループになっちゃうみたいですね。

  • クリックする
  • @HostListener('click') がついた onClick が呼び出される
  • this.click.emit() する
  • ここから回り回って onClick が再帰的に呼び出される

といった流れになっているようです。

仕方なく click の名前を clickHost に変えたらエラーが出なくなりました。そりゃそうですね。

@Component({
  selector: 'hello',
  template: `<h1>Hello!</h1>`,
})
export class HelloComponent  {
  @Output() clickHost = new EventEmitter<void>();

  @HostListener('click')
  onClick (): void {
    this.clickHost.emit();
  }
}

当然といえば当然の話なのですが、ググっても情報がヒットしなかったので、誰かの助けになればと思って書きました 🙏