質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

Q&A

解決済

3回答

6989閲覧

Vueの初歩的な質問になります。

matsuo_basho

総合スコア88

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

0グッド

0クリップ

投稿2021/07/25 05:12

編集2021/07/25 07:11

いつも大変お世話になっております。
久しぶりにVue CLIを用いて簡単なシミュレーションアプリを作成しているのですが、
APIで取得したデータをhtml上に展開するところでハマってしまっています。

例えば、

const plan = { "id": 805, "date": "2021-02-20T23:49:22", "date_gmt": "2021-02-20T14:49:22", "title": { "rendered": "タイトルタイトルタイトルタイトル" } }

というデータがあった際に、{{ plan.title.rendered }} でタイトルが出力されると思うのですが、
なぜか 下記2つのエラーが出てしまいます。

Uncaught TypeError: Cannot read property 'rendered' of undefined

[Vue warn]: Unhandled error during execution of render function at <Plan> at <Simulation>

ちなみに、{{ plan.title }} では、ちゃんと"rendered": "タイトルタイトルタイトルタイトル"と出力されます。

深い階層になった途端にエラーが発生してしまうのでなんでだろう?とはてな状態です。

どなたか詳しい方がいらっしゃれば、ご教授いただけますと幸いです。

それではどうぞ宜しくお願い致します。

###環境
% vue --version
@vue/cli 5.0.0-beta.2

ソースコード

javascript

1// store/index.js 2 3import { createStore } from 'vuex' 4import axios from 'axios' 5 6export default createStore({ 7 8 state : { 9 plan : "" 10 }, 11 12 getters : { 13 plan : (state) => state.plan, 14 }, 15 16 mutations : { 17 setPlan : (state, { plan }) => { 18 state.plan = plan 19 } 20 }, 21 22 actions : { 23 24 async fetchPlan({ commit }, { id }){ 25 26 const url = `https://localhost:8890/wp-json/wp/v2/posts/${id}/`; 27 28 const planRowData = await axios.get(url) 29 const plan = planRowData.data 30 31 if( !plan.id ) throw new Error('Invalid Post.') 32 33 commit('setPlan', { plan }) 34 35 } 36 37 } 38 39})
// App.vue <template> <div id="simulation" class="simulation"> <section> <Plan/> </section> </div> </template> <script> import Plan from './components/Plan' export default { name : 'Simulation', components : { Plan } } </script>
// Plan.vue <template> <div> {{ plan.title.rendered }} // Uncaught TypeError: Cannot read property 'rendered' of undefined 発生! </div> </template> <script> import { mapGetters, mapActions } from "vuex"; export default { name : 'Plan', created(){ this.fetchPlan({ id : 805 }); }, computed : { ...mapGetters([ 'plan' ]) }, methods : { ...mapActions([ 'fetchPlan' ]) } } </script>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

始めplunには何も入っていません。

そのため{{ plun.title }}undefinedになり、何も表示されません。
その後にgetされたデータが入ってきて、plunの値が更新されるので結果的に{{ plun.title }}は中の値が表示されます。

しかし{{ plan.title.rendered }}に関しては、そもそもplun.titleundefinedだった場合、undefinedに対してプロパティrenderedを指定しているのでエラーになります。

それを回避したい場合はgetが終わってから表示させるか、{{ plan.title && plan.title.rendered }}のようにすればよいかと思います。

※Optional Chainingを使うとplan.title?.renderedのようにより簡潔に書けますが、Vueのテンプレート内では使用できません。

投稿2021/07/26 12:02

編集2021/07/26 12:12
taku-hu

総合スコア176

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuo_basho

2021/07/27 07:59

ご回答の方ありがとうございます! ご提案いただいたように{{ plan.title && plan.title.rendered }}とすることで、 無事に表示することができました。 ありがとうございます。 1つ質問があるのですが、ご提案いただいた以下の方法を選択した場合、 どのようにgetが完了するのを待てば良いのでしょうか? これまで今の書き方でget完了時にリアクティブにデータが同期されるので、 getを待って処理を書かずとも、待っていれば自動で更新されるものだと思っておりました。。 「それを回避したい場合はgetが終わってから表示させるか」
taku-hu

2021/07/27 08:34

例えば`isLoading`のようなものを定義して、fetchPlanの最初と最後で切り替えて管理します。 それをtemplate側で、 ``` <template v-if="isLoading">  <p>Loading...</p> </template> <template v-else>  <Plan /> </template> ``` のようにして出しわける事が出来ます。 それと試験段階ではありますがVue3にはSuspenseという機能があり、これも非同期処理を待ってコンテンツの表示を行うことができます。 https://v3.ja.vuejs.org/guide/migration/suspense.html
matsuo_basho

2021/07/27 10:49

なるほど、よく分かりました! 自分でもすでに使っている技術でした。。 こちらについても試してみたいと思います!ありがとうございます!! Suspenseという機能についてもありがとうございます! 大変勉強になります!ただし以下のように記述がありましたので、本番利用は避けたいと思います(笑) >本番のアプリケーションでは使用しないでください。
guest

0

データ取得前の段階ではplantitle.renderedが存在しないためエラーになっている気がします。
plan.titleの場合エラーにならないのは、こちらはデータ取得前の段階でもundefinedになるだけだからです)

またVue2ではオブジェクトのプロパティ追加を検出できないため、あらかじめdataに定義しておくかthis.$set()等のメソッドを使用して追加する必要があります。

planの初期値を以下に変えてみたらどうなるでしょうか?

plan: { title: { rendered: '' } }

投稿2021/07/26 05:02

編集2021/07/26 05:46
Masa-Shin

総合スコア269

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

{{ plan.title["rendered"] }}

とすると表示されますでしょうか?

投稿2021/07/25 06:43

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuo_basho

2021/07/25 07:10

早速のご回答ありがとうございます! {{ plan.title["rendered"] }} を試してみましたが改善せずです、、! 以下のエラーも出ていたようです。(と言いつつよく意味がわからないのですが、、。) [Vue warn]: Unhandled error during execution of render function at <Plan> at <Simulation>
退会済みユーザー

退会済みユーザー

2021/07/25 07:21

そうなんですね・・・ 実行時エラーですよね、文法エラーではなくて・・・ Planの中で、render関数を実行するときにエラーがでちゃってるみたいですが・・・
matsuo_basho

2021/07/25 07:29

うーむ、よくわからないですね(笑) store側で plan.title.renderd は取得できたので、stateにplanTitleを作成して対応してます。 const planTitle = plan.title.renderd こんな感じですね。
退会済みユーザー

退会済みユーザー

2021/07/25 07:31 編集

ちなみに、renderという関数を使っている場所はありますか?
matsuo_basho

2021/07/25 07:34

いえ、質問文に掲載しているソースコードが全てですので、 render()を利用しているところはありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問