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

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

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

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

Vuex

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2494閲覧

VuexでUncaught (in promise) TypeError: Cannot read property 'id' of undefined

matsuo_basho

総合スコア88

Vue.js

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

Vuex

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/08/20 17:19

お世話になっております。
現在VuexでREST APIを利用してCRUDの勉強をしています。

まずはAPIが提供しているJSONデータを取得してデータの「一覧」「詳細(1件)」を取得・出力を試みています。

取得できるデータは以下となります。

一覧 : http://127.0.0.1:8000/api/

json

1[ 2 { 3 "id": 1, 4 "title": "買い物", 5 "body": "宇宙兄弟を買いに行く" 6 }, 7 { 8 "id": 2, 9 "title": "メール返信", 10 "body": "田中さんにメール" 11 } 12] 13

詳細(1件) : http://127.0.0.1:8000/api/1/

json

1{ 2 "id": 1, 3 "title": "買い物", 4 "body": "宇宙兄弟を買いに行く" 5}

いま抱えている問題ですが、
Vuexにて 詳細(1件) を取得し、表示する際に Uncaught (in promise) TypeError: Cannot read property 'id' of undefined というエラーが毎回出力されてしまうのですが、
どの部分でエラーを出力しているのか検討もつかない状態です。

イメージ説明

もし解決方法が分かる方がいらっしゃればご教授いただけると幸いです。

環境

@vue/cli 4.5.4
Vuex
Vue Router
axios

javascript

1// frontend/src/services/api.js 2 3import axios from 'axios' 4 5 6const api = axios.create({ 7 8 baseURL: process.env.VUE_APP_ROOT_API, 9 timeout: 5000, 10 headers: { 11 12 'Content-Type': 'application/json', 13 'X-Requested-With': 'XMLHttpRequest' 14 15 } 16 17}) 18 19export default api 20

javascript

1// frontend/src/store/index.js 2 3import {createStore} from 'vuex' 4import api from "@/services/api"; 5 6const MUTATION_TYPES = { 7 8 GET_TODOS_REQUEST: 'GET_TODOS_REQUEST', 9 10 GET_TODOS_SUCCESS: 'GET_TODOS_SUCCESS', 11 GET_TODO_SUCCESS: 'GET_TODO_SUCCESS', 12 13 GET_TODOS_FAILURE: 'GET_TODOS_FAILURE', 14 GET_TODO_FAILURE: 'GET_TODO_FAILURE' 15 16} 17 18export default createStore({ 19 20 state: { 21 22 isFetching: false, 23 todos: [], 24 error: null 25 26 }, 27 28 getters: { 29 30 /* 一覧取得 */ 31 getTodos: state => { 32 return state.todos; 33 }, 34 35 /* 詳細取得 */ 36 getTodo: state => id => { 37 return state.todos.find(todo => todo.id === id); 38 }, 39 40 }, 41 42 mutations: { 43 44 /* 取得中 */ 45 [MUTATION_TYPES.GET_TODOS_REQUEST](state){ 46 47 state.isFetching = true 48 49 }, 50 51 /* 一覧取得完了 */ 52 [MUTATION_TYPES.GET_TODOS_SUCCESS](state, todos){ 53 54 state.isFetching = false 55 state.todos = todos 56 57 }, 58 59 /* 詳細取得完了 */ 60 [MUTATION_TYPES.GET_TODO_SUCCESS](state, todo){ 61 62 state.isFetching = false 63 state.todo = todo 64 65 }, 66 67 /* 一覧取得失敗 */ 68 [MUTATION_TYPES.GET_TODOS_FAILURE](state, err){ 69 70 state.isFetching = false 71 state.todos = null 72 state.error = err 73 74 }, 75 76 /* 詳細取得失敗 */ 77 [MUTATION_TYPES.GET_TODO_FAILURE](state, err){ 78 79 state.isFetching = false 80 state.todo = null 81 state.error = err 82 83 } 84 85 }, 86 87 actions: { 88 89 /* 一覧取得 */ 90 setTodos({commit}){ 91 92 commit(MUTATION_TYPES.GET_TODOS_REQUEST) 93 94 return api.get('/') 95 96 .then(response => { 97 98 commit(MUTATION_TYPES.GET_TODOS_SUCCESS, response.data) 99 100 }) 101 102 .catch(error => commit(MUTATION_TYPES.GET_TODOS_FAILURE, error)) 103 104 }, 105 106 /* 詳細取得 */ 107 setTodo({commit}, id){ 108 109 commit(MUTATION_TYPES.GET_TODOS_REQUEST) 110 111 return api.get('/' + id) 112 113 .then(response => { 114 115 commit(MUTATION_TYPES.GET_TODO_SUCCESS, response.data) 116 117 }) 118 119 .catch(error => commit(MUTATION_TYPES.GET_TODO_FAILURE, error)) 120 121 }, 122 123 }, 124 125}) 126

javascript

1// frontend/src/router/index.js 2 3import {createRouter, createWebHistory} from 'vue-router' 4 5 6const routes = [ 7 8 { 9 path: '/', 10 name: 'Todos', 11 component: () => import('@/views/Todos.vue') 12 }, 13 { 14 path: '/:id', 15 name: 'Todo', 16 component: () => import('@/views/Todo.vue') 17 }, 18 19] 20 21const router = createRouter({ 22 history: createWebHistory(process.env.BASE_URL), 23 routes 24}) 25 26export default router

html

1// frontend/src/views/Todos.vue 2 3<template> 4 <div class="todos"> 5 6 <h1>Todo</h1> 7 8 <ul> 9 <li v-for="todo in todos" :key="todo.id"> 10 <a :href="todo.id">{{ todo.body }}</a> 11 </li> 12 </ul> 13 14 </div> 15</template> 16 17 18<script> 19import {mapState} from "vuex"; 20 21export default { 22 23 name: 'Todos', 24 25 computed: { 26 27 ...mapState(['todos']) 28 29 }, 30 31 created(){ 32 33 this.$store.dispatch('setTodos') 34 35 }, 36 37} 38 39</script>

html

1// frontend/src/views/Todo.vue 2 3<template> 4 <div id="todo"> 5 6 7 <h1>Todo Detail</h1> 8 9 10 ID : {{ todo.id }} 11 12 <hr> 13 14 TITLE : {{ todo.title }} 15 16 <hr> 17 18 {{ todo.body }} 19 20 21 </div> 22</template> 23 24 25<script> 26import {mapState} from "vuex"; 27 28export default { 29 name: 'Todo', 30 31 32 computed: { 33 34 ...mapState(['todo']) 35 36 }, 37 38 created(){ 39 40 const id = this.$route.params.id 41 this.$store.dispatch('setTodo', id) 42 43 }, 44 45} 46 47</script>

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

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

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

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

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

guest

回答1

0

ベストアンサー

frontend/src/store/index.js内の下記の箇所で、state.todoに代入をされていますが、Vuexのstateにtodoが定義されていません。
よって、APIから取得したデータが正しくstoreに格納されておりません。

javascript

1// frontend/src/store/index.js 2[MUTATION_TYPES.GET_TODO_SUCCESS](state, todo){ 3 4 state.isFetching = false 5 state.todo = todo 6}

また、frontend/src/views/Todo.vueにおいても ...mapState(['todo'])と記述されておりますが、同様にstate.todoは存在しないためundefiendとなっていると思われます。
そのため、Uncaught (in promise) TypeError: Cannot read property 'id' of undefined というエラーが表示されています。

gettersにおいてgetTodoを定義されていらっしゃるので、下記のように修正案が考えられます。

javascript

1// frontend/src/store/index.js 2[MUTATION_TYPES.GET_TODO_SUCCESS](state, todo){ 3 4 state.isFetching = false 5 state.todo.push(todo) 6}

html

1// frontend/src/views/Todo.vue 2 3<template> 4 <div id="todo"> 5 6 7 <h1>Todo Detail</h1> 8 9 10 ID : {{ todo.id }} 11 12 <hr> 13 14 TITLE : {{ todo.title }} 15 16 <hr> 17 18 {{ todo.body }} 19 20 21 </div> 22</template> 23 24 25<script> 26import {mapGetters} from "vuex"; 27 28export default { 29 name: 'Todo', 30 31 32 computed: { 33 todo() { 34 this.getTodo(this.$route.params.id) 35 }, 36 ...mapGetters(['getTodo']) 37 38 }, 39 40 created(){ 41 // すでにtodosに対象のデータが存在する場合には何もしない 42 if (this.todo) { 43 return 44 } 45 const id = this.$route.params.id 46 this.$store.dispatch('setTodo', id) 47 48 }, 49 50} 51 52</script>

投稿2020/08/21 12:19

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

matsuo_basho

2020/08/22 02:19

回答ありがとうございます! わりと初歩的なミスでしたね、、。 助かりました、、!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問