Angular のlength of null の対処(デバッグ)


デモアプリを使っていると、こんなエラーに遭遇した。これは、最初にアクセスした時のみ発生した。

自分のコードを見て、本番コードではなく、スパイクのプロジェクトを作ってみる。同僚が localStorage のfix を入れたところで、発生しているので、多分それと思われる。

ng new local

このリポを一応あげとく

*Angular Experiment

起動時初回のみなので、localStorage にマトを絞って再現させてみる。

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  cars = [];
  constructor() {
    this.cars = JSON.parse(localStorage.getItem("cars"));
    console.log('this.cars:' + this.cars);
  }

  ngOnInit(): void {
    setTimeout(() => {
    this.cars = [{"name": "subaru"}];
    localStorage.setItem("cars", JSON.stringify(this.cars));
    }, 3000)

  }
}
<h2>Here are some links to help you start: </h2>
car number is {{cars.length}}
<ul>
  <li *ngFor="let c of cars"> {{c.name}} </li>
</ul>
<ul>

ブラウザの開発者モードで調べると、html のlength のところで、null になっている。コードをみると、デフォルト値でnull になっている。なんでだろ、、、ちなみに、setTimeout() をかけているのは、タイムアウトをここでかけないと、画面の描画の前に、ngOnInit() が動いてしまうため、問題が発生しないから。(本当のアプリはリモートコール)これで再現する。

export class AppComponent {
  title = 'app';
  cars = [];
  constructor() {
    this.cars = JSON.parse(localStorage.getItem("cars"));
    console.log('this.cars:' + this.cars);
  }

  ngOnInit(): void {
    setTimeout(() => {
    this.cars = [{"name": "subaru"}];
    localStorage.setItem("cars", JSON.stringify(this.cars));
    }, 3000)

  }
}

ポイントはシンプルで、最初に、cars = [] を書いているけど、JSON.parse(localStorage.getItem("cars"));で上書きしているので、localStorage がなければ、null になるという問題。ということは、解決策は、デフォルト値を設定すると良い。|| をつけることで、null の場合デフォルト値になる。

    this.cars = JSON.parse(localStorage.getItem("cars")) || [];

解決。プルリクエスト書いた。