TypeError: Cannot read properties of null (reading '0')


原因:NULLの要素にアクセスしようとした

想定していた配列が作成されていませんでした。

以下詳細

Laravel & Vue.jsの構成で、ニコニコ動画のコンテンツを扱うSPAサイトを作成していました。
その中で、動画視聴用URLからコンテンツIDを抜き取り、サムネイル取得用のURLを生成しようと試みていました。

2つのURLの構成は以下の通りです。

//動画視聴URL(千本桜)
https://nico.ms/sm15630734

//サムネイル取得URL
https://ext.nicovideo.jp/thumb/sm15630734

作成したComponentは以下の通りです。
自作のAPIから取得した動画視聴URLに対し、match()を使って正規表現にあてはまる部分文字列を抜き出し、contentIdに格納。match()の返り値は配列なので、contentId[0]とし、最初の要素のみを利用しています。

Component

{{– 中略 -}}

data: function(){
    return {
        URL: '',
        thumb: '',
    }
}

{{– 中略 -}}

methods: {
    getThumb(){

        {{– axiosのGET処理 -}}

        this.URL = res.data.URL;
        var contentId = this.URL.match(/^sm\d+$/);
        this.thumb ='https://ext.nicovideo.jp/thumb/'+ contentId[0];
    }
}

こちらを実行したところ、表題のエラーが発生しました。

TypeError: Cannot read properties of null (reading '0')

最初は this.URL にアクセスできていないと判断し、以下のようなthisのスコープに関する記事を参照していましたが、しばらくして、配列contentIdに値が入っていないことを怒られていることに気づきました。

thisのスコープに関する記事↓
https://tadaken3.hatenablog.jp/entry/vue-scope-this

原因はもちろん正規表現が正しく指定されていないことでした。初めて正規表現を使用したので、誤りになかなか気づきませんでした。

不適切な正規表現

var contentId = this.URL.match(/^sm\d+$/);

正しくは

var contentId = this.URL.match(/(?:sm|nm|so|ca|ax|yo|nl|ig|na|cw|z[a-e]|om|sk|yk)\d{1,14}\b/);

こちらの正規表現は以下の記事を参考にさせていただきました。
https://matatsuna.hatenablog.com/entry/2019/10/21/111214

現代では、ほぼsmから始まる動画のIDですが、昔は色々なものがあったんですね。