はじめに
タイトルの通り、Vue3を使って画面を開いたら「RangeError: Maximum call stack size exceeded」なんて、よくわからんエラーメッセージが出た話です。
まず、Vue3 + Quesarを使って、手始めにコンポーネントを作ってみようとQuasarの「q-table」をWrapしたコンポーネントを作りました。
しかし、いざ「npm run dev」を実行すると、Vueのロゴだけ出て表が表示されない・・・?開発者ツールを使ってコンソールを見るとタイトルのエラーが。。。
事象
本当は、ロゴの下に2列2行の表が表示される想定だったのですが、その描画までたどり着かず、コンソールにエラーメッセージが出力されている状態になっています。
開発環境
記事を作成した時点でのバージョンは以下の通りです。
- Windows 10
- Vue 3.2.45
- Quasar 2.11.5
何らかの変更があったらバージョン上げるかもしれないので、最新はgithubに公開しているpackage.jsonで確認してください。(コードへのリンク)
原因と解決策
原因
コンポーネントが自分のコンポーネントを呼び出すような作りになっていたためでした。作りが悪かった。。。
サンプルコード
コンポーネントのコード例です。とっても単純化してます。Quasar関係なく発生します。
ComponentA.vue
<template>
<!-- ↓自コンポーネントを呼び出している -->
<ComponentA />
<div>コンポーネントA</div>
</template>
結果、「ComponentAをレンダリングし続け、stack sizeを超過する」というオチでした。
解決策
自コンポーネントを呼ばないようにしましょう。
が一番の解決策ですね。ただ、今回このケースにはまってしまった実例も書いておきます。
実例
実装してしまった背景
あまり理解をしていない状態、何とかなるだろ精神と以下の思いで作り出しました。
- 表を使ってレイアウトしたかった
- Quasarを使ってみたかった(Quasar超初心者)
- QTableのサンプルは長かったので分離(=コンポーネント化)したかった
コンポーネント化自体はそこまで悩むことなく書き出せたのですが、名前が思いつかなかったんですよね。
そこで、別ファイルのソースコードにしておけば、違うものと認識するのではないか?と思い込んで「QTable.vue」という名前でコンポーネント名を決めてしまったんですねー。。
実装概要
App.vue
import QTable from ./component/QTable.vue
:(省略)
<header><img alt="Vue logo" …></header> <!-- ロゴ表示 -->
<main><QTable /></main>
:(省略)
component/QTable.vue
:(script部分省略)
<template>
<div class="q-pa-md">
<!-- q-table = QTable。従って自コンポーネントの呼び出しとなり永久ループ -->
<q-table
title="サンプルテーブル"
:rows="rows"
:columns="columns"
row-key="title"
/>
</div>
</template>
結果、同じコンポーネントであると認識されてしまい、ひたすら自コンポーネントを描画しようとしてstack sizeを超過したというわけでした。
名前をQTable.vue → CustomQTable.vueに変更したところ、問題が解消され想定される画面表示ができるようになりました。
しかし結局名前がイケてない。
問題解消後の画面
サンプルテーブルがロゴの下に表示され、コンソールにもエラーが表示されることが無くなりました。Vue3 + Quasarで表の表示ができるようになった、という成功体験もゲット。
さいごに
あまり雑すぎる名前を付けるのは良くない、という学びを得ました。あとはどういうスコープになっているのか、というところも注目しないといけないな、と確認できました。(正直JavaScript系のスコープは理解があやふやなところが多いので)
注意点も一つ学べたので、また作りながら不具合と一緒に育っていきましょう。
ソースコード
この記事を書く起因となったソースコードは以下で公開しています。(GitHub)
コメント