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

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

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

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

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Vuex

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

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

JavaScript

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

Q&A

0回答

867閲覧

Vueを使ったアプリで、Firestoreのデータを参照できなくなる

gnuuu_07

総合スコア10

Vue.js

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

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Vuex

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

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

JavaScript

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

0グッド

0クリップ

投稿2020/09/27 04:43

編集2022/01/12 10:55

Vuexを使った読書記録アプリケーションを作っています。
Firestoreに登録したデータを参照できずに困っています。

書籍一覧から書籍を選択すると、書籍の詳細ページへ遷移し、詳細ページには感想などを入力するフォームもあります。
感想を入力して登録ボタンを押すとホーム画面に遷移し、感想を登録した書籍が表示される仕様です。

現在、感想を入力して登録ボタンを押し、ホーム画面に遷移した際は、登録した書籍が表示されるのですが、ホーム画面をリロードすると登録した書籍情報が消えてしまうという状況です。

以下のような二つのエラーが出るため、Firestoreのルール設定なども見直してみましたが、解決できません。
FirebaseError: Function CollectionReference.add() requires its first argument to be of type object, but it was: undefined

Error in v-on handler: "FirebaseError: [code=invalid-argument]: Function CollectionReference.add() requires its first argument to be of type object, but it was: undefined"

以下、コードになります。量が多くなってしまっていますが、よろしくお願いいたします。

Firestore

1rules_version = '2'; 2service cloud.firestore { 3 match /databases/{database}/documents { 4 match /users/{userId}/books/{bookId} { 5 allow read, update, delete: if request.auth.uid == userId; 6 allow create: if request.auth.uid != null; 7 } 8 } 9}

JavaScript

1store/index.js 2 3import Vue from 'vue' 4import Vuex from 'vuex' 5 6import firebase from 'firebase' 7Vue.use(Vuex) 8 9export default new Vuex.Store({ 10 state: { 11 //レビューと書籍情報 12 books: [], 13 //編集/洗濯中の書籍 14 current: null, 15 16 login_user: null 17 }, 18 getters: { 19 //登録済みのレビュー数 20 bookCount(state){ 21 return state.books.length 22 }, 23 //全てのレビュー 24 allBooks(state){ 25 return state.books 26 }, 27 //指定したページの情報を取得 28 getRangeByPage(state){ 29 return page =>{ 30 const size = 3 31 return state.books.slice((page-1)*size,(page-1)*size+size) 32 } 33 }, 34 //idをもとに情報を取得 35 getBookById(state){ 36 return id =>{ 37 return state.books.find(book=>book.id===id) 38 } 39 }, 40 //現在編集中の作業 41 current(state){ 42 return state.current 43 }, 44 uid: (state)=>(state.login_user ? state.login_user.uid : null) 45 }, 46 mutations: { 47 updateCurrent(state,payload){ 48 state.current = payload 49 }, 50 updateBook(state,payload){ 51 let book = this.getters.getBookById(payload.id) 52 if(book){ 53 //二つのオブジェクトをマージ 54 Object.assign(book,payload) 55 }else{ 56 state.books.push(payload) 57 } 58 }, 59 load(state) { 60 if(localStorage.getItem('store')) { 61 //localstorageから取得したjson文字列を変換 62 const store = JSON.parse(localStorage.getItem('store')) 63 //stateを置き換える 64 this.replaceState(Object.assign(state,store)) 65 } 66 }, 67 setLoginUser(state,user) { 68 state.login_user = user 69 }, 70 deleteLoginUser(state) { 71 state.login_user = null 72 }, 73 addBook(state, {id,book}) { 74 book.id = id; 75 state.books.push(book); 76 } 77 }, 78 actions: { 79 updateCurrent({commit},payload){ 80 commit('updateCurrent',payload) 81 }, 82 updateBook({commit},payload){ 83 commit('updateBook',payload) 84 }, 85 load({commit}) { 86 commit('load') 87 }, 88 googleLogin() { 89 const google_auth_provider = new firebase.auth.GoogleAuthProvider() 90 firebase.auth().signInWithRedirect(google_auth_provider) 91 }, 92 setLoginUser({commit}, user) { 93 commit('setLoginUser', user) 94 }, 95 logout() { 96 firebase.auth().signOut() 97 }, 98 deleteLoginUser({commit}) { 99 commit('deleteLoginUser') 100 }, 101 //入力したレビューをFirestoreに登録 102 addBook({getters, commit},book) { 103 if(getters.uid){ 104 firebase 105 .firestore() 106 .collection(`users/${getters.uid}/books`) 107 .add(book) 108 .then((doc)=>{ 109 commit("addBook", {id:doc.id,book}); 110 }) 111 } 112 }, 113 //Firestoreからデータを参照 114 fetchBooks({getters, commit}) { 115 firebase.firestore().collection(`users/${getters.uid}/books`).get().then(snapshot=>{ 116 snapshot.forEach(doc=>commit('addBook',{id:doc.id,book:doc.data()})) 117 }) 118 } 119 }, 120 modules: { 121 } 122}) 123

JavaScript

1Bookform.vue(レビュー入力画面) 2 3<template> 4 <div id="form"> 5 <BookInfo :book="book"></BookInfo> 6 <hr> 7 <el-form ref="form" :model="form" :rules="rules"> 8 <el-form-item label="読了日"> 9 <el-date-picker type="date" v-model="form.read"></el-date-picker> 10 </el-form-item> 11 <el-form-item label="感想" prop="memo"> 12 <el-input type="textarea" v-model="form.memo"></el-input> 13 </el-form-item> 14 <el-form-item> 15 <div class="button"> 16 <el-button type="primary" @click="submit">登録</el-button> 17 </div> 18 </el-form-item> 19 </el-form> 20 </div> 21</template> 22 23<script> 24import BookInfo from '../components/Bookinfo.vue' 25import { mapGetters, mapActions } from 'vuex' 26export default { 27 name: 'book-form', 28 components: { 29 BookInfo 30 }, 31 data(){ 32 return { 33 //洗濯中の書籍 34 book:{}, 35 //フォームの内容 36 form:{ 37 read: new Date(), 38 memo: '' 39 }, 40 //バリデーションチェック 41 rules:{ 42 memo: [ 43 {required: true, message: 'メモが未入力です', trigger: 'change'} 44 ] 45 } 46 } 47 }, 48 computed: mapGetters(['current', 'getBookById']), 49 50 created(){ 51 if(!this.current){ 52 this.$router.push('/') 53 } 54 this.book=Object.assign({},this.current) 55 }, 56 57 mounted(){ 58 let b = this.getBookById(this.book.id) 59 60 if(b){ 61 this.form.read = b.read 62 this.form.memo = b.memo 63 } 64 }, 65 66 methods:{ 67 ...mapActions(['updateBook','updateCurrent']), 68 69 submit(){ 70 //入力値の検証 71 this.$refs['form'].validate((valid)=>{ 72 if(valid){ 73 this.updateBook( 74 Object.assign({},this.book,this.form) 75 ) 76 } 77 78 this.updateCurrent(null) 79 80 this.$store.dispatch('addBook') 81 82 this.$notify({ 83 title: 'Book Recorder', 84 message: this.$createElement('p', {style:'color: #009'},'読書情報の登録/更新に成功しました。'), 85 duration: 2000 86 }) 87 88 this.form.read = new Date() 89 this.form.memo = '' 90 91 this.$router.push('/home') 92 }) 93 } 94 } 95} 96</script> 97 98<style> 99 .button { 100 text-align: center; 101 } 102</style>

JavaScript

1Home.vue(レビュー登録済みの書籍を一覧表示) 2 3<template> 4 <div class="list"> 5 <!-- <img alt="Vue logo" src="../assets/logo.png"> 6 <HelloWorld msg="Welcome to Your Vue.js App"/> --> 7 <p>{{bookCount}}件の読書情報が記録されています</p> 8 <!-- 書籍情報を表示 --> 9 <BookInfo v-for="(b,i) of books" :linkable="true" :book="b" :index="i+1" :key="b.id"></BookInfo> 10 <!-- ページャーの生成 --> 11 <div> 12 <el-pagination background layout="prev,pager,next" :total="bookCount" :page-size="3" @current-change="onchange"></el-pagination> 13 </div> 14 </div> 15</template> 16 17<script> 18// @ is an alias to /src 19// import HelloWorld from '@/components/HelloWorld.vue' 20import {mapGetters} from 'vuex'; 21import BookInfo from '../components/Bookinfo.vue' 22 23export default { 24 name: 'Home', 25 data(){ 26 return { 27 books: [] 28 } 29 }, 30 components: { 31 BookInfo 32 }, 33 computed: mapGetters(['bookCount','getRangeByPage']), 34 //ページ変更時にレビュー情報を新たにセット 35 methods: { 36 onchange(page){ 37 this.books = this.getRangeByPage(page) 38 } 39 }, 40 //初期化時に1ページ目の情報を取得 41 mounted(){ 42 this.books = this.getRangeByPage(1) 43 } 44} 45</script>

JavaScript

1App.vue 2 3<template> 4 <div id="app"> 5 <h2>Book Recorder</h2> 6 <!-- <img src="./assets/logo.png"> 7 <div> 8 <p> 9 If Element is successfully added to this project, you'll see an 10 <code v-text="'<el-button>'"></code> 11 below 12 </p> 13 <el-button>el-button</el-button> 14 </div> 15 <HelloWorld msg="Welcome to Your Vue.js App"/> --> 16 <!-- メインメニュー --> 17 <el-menu mode="horizontal" background-color="orange" text-color="#fff" active-text-color="#ffd04b"> 18 <el-menu-item index="1" v-if="$store.state.login_user"> 19 <router-link to="/home">ホーム</router-link> 20 </el-menu-item> 21 <el-menu-item index="2"> 22 <router-link to="/search">検索</router-link> 23 </el-menu-item> 24 <el-menu-item index="3"> 25 <router-link to="" @click.native="logout" v-if="$store.state.login_user">ログアウト</router-link> 26 <router-link to="/login" v-if="!$store.state.login_user">ログイン</router-link> 27 </el-menu-item> 28 <el-menu-item v-if="$store.state.login_user"> 29 30 </el-menu-item> 31 </el-menu> 32 <!-- ルーティングの表示 --> 33 <router-view /> 34 </div> 35</template> 36 37<script> 38// import HelloWorld from './components/HelloWorld.vue' 39import firebase from 'firebase' 40import { mapActions } from 'vuex' 41export default { 42 name: 'app', 43 // components: { 44 // HelloWorld 45 // } 46 created() { 47 firebase.auth().onAuthStateChanged(user=>{ 48 if(user){ 49 //ユーザー情報をセット 50 this.setLoginUser(user) 51 //Firestoreから参照 52 this.fetchBooks() 53 this.$router.push('/home') 54 } else { 55 this.deleteLoginUser() 56 this.$router.push('/') 57 } 58 }) 59 }, 60 methods: { 61 ...mapActions(['setLoginUser','deleteLoginUser','logout','fetchBooks']) 62 } 63} 64</script> 65 66<style> 67#app { 68 /* font-family: 'Avenir', Helvetica, Arial, sans-serif; 69 -webkit-font-smoothing: antialiased; 70 -moz-osx-font-smoothing: grayscale; 71 text-align: center; 72 color: #2c3e50; 73 margin-top: 60px; */ 74} 75</style> 76

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問