📑
ユーザー詳細、ファイル詳細でクリックが早いと、storeの前のデータが表示されてしまう
原因調査
ハマった
apiを通信する処理のコードは、全て非同期にしているため、原因が不明な状態
4、5あたりが怪しいと踏んでいて、4の時点で、本来なら対象の音声ファイルを押下すれば、そのファイルの配列のインデックスが取得できる想定なのですが、できていなそう
非同期と関係なさそうと踏んでいる。(最初のトップページでのデータが問題なく格納できているため)
トップページの表示
1
pages/TopAfterLogin.vue
asyncData: async function(context) {
// すべての音声ファイルを取得する
await context.store.dispatch('musicFiles/musicFileTopPageData')
},
2
store/musicFiles.js
musicFileTopPageData(context) {
let items = []
this.$axios.$get('api/musicFileData')
.then(response => {
items = response
console.log(items)
context.commit('setmusicFileTopPageData', items)
})
.catch(error => {
console.log(error)
})
},
3(ここでstoreに格納)
store/musicFiles.js
setmusicFileTopPageData (state, items) {
state.items = items
console.log(items)
},
トップから詳細への遷移
4
pages/TopAfterLogin.vue
<div class="content" v-for="(item, index) in $store.getters['musicFiles/items'].items" :key="index" @click="setMusicFileData(item.title, item.cover_image, item.music_file, item.user_name, item.user_id, item.id, item.description, item.user_icon)">
pages/TopAfterLogin.vue
setMusicFileData (clickedFileTitle, clickedFileCoverImage, clickedFileMusicfile, clickedFileUserName, clickedFileUserId, clickedFileId, clickedFileUserDescription, clickedFileUserUserIcon) {
this.clickedFileTitle = clickedFileTitle
this.clickedFileCoverImage = clickedFileCoverImage
this.clickedFileMusicfile = clickedFileMusicfile
this.clickedFileUserName = clickedFileUserName
this.clickedFileUserId = clickedFileUserId
this.clickedFileId = clickedFileId
this.clickedFileUserDescription = clickedFileUserDescription
this.clickedFileUserUserIcon = clickedFileUserUserIcon
console.log(clickedFileUserDescription)
console.log(clickedFileUserUserIcon)
this.$store.dispatch('musicFiles/setMusicFileData', {
clickedFileTitle: this.clickedFileTitle,
clickedFileCoverImage: this.clickedFileCoverImage,
clickedFileMusicfile: this.clickedFileMusicfile,
clickedFileUserName: this.clickedFileUserName,
clickedFileUserDescription: this.clickedFileUserDescription,
clickedFileUserUserIcon: this.clickedFileUserUserIcon,
// フォローで渡すためのやつ
clickedFileUserId: this.clickedFileUserId,
clickedFileId: this.clickedFileId,
})
},
5(ここで既に前に表示したデータのidが入っている)
store/musicFiles.js
setMusicFileData(context, payload) {
const musicFiledatum = {
clickedFileTitle: payload.clickedFileTitle,
clickedFileCoverImage: payload.clickedFileCoverImage,
clickedFileMusicfile: payload.clickedFileMusicfile,
clickedFileUserName: payload.clickedFileUserName,
clickedFileUserId: payload.clickedFileUserId, //storeへ格納→詳細ページでのasyckdataでのapi取得に使用したい
clickedFileId: payload.clickedFileId, //storeへ格納→詳細ページでのasyckdataでのapi取得に使用したい
clickedFileUserDescription: payload.clickedFileUserDescription,
clickedFileUserUserIcon: payload.clickedFileUserUserIcon,
}
const musicFileData = [];
musicFileData.push(musicFiledatum)
context.commit('setMusicFileDataMutations', musicFileData)
},
6(ここで既に前に表示したデータのidがstoreに格納)
store/musicFiles.js
setMusicFileDataMutations(state, musicFileData) {
// console.log(musicFileData)
// console.log(state.musicFileData)
state.musicFileData = musicFileData
},
ファイル詳細画面での表示〜
7(既に前に表示したデータのapiのurlに格納されるパラメータとなってしまう)
pages/_user/_title.vue
asyncData: async function(context) {
context.store.commit("loading/setLoading", true)
let clickedFileUserId = ''
// 配列でclickedFileUserId取得
context.store.getters['musicFiles/musicFileData'].forEach(musicFiledatum => {
clickedFileUserId = musicFiledatum.clickedFileUserId
});
console.log(clickedFileUserId)
let clickedFileId = ''
context.store.getters['musicFiles/musicFileData'].forEach(musicFiledatum => {
clickedFileId = musicFiledatum.clickedFileId
});
console.log(clickedFileId)
await context.store.dispatch('musicFiles/musicDetailPageData', {
clickedLoginUserId: context.store.state.auth.user.id,
clickedFileId: clickedFileId,
clickedFileUserId: clickedFileUserId,
})
context.store.commit("loading/setLoading", false)
},
解決
ライフサイクルフックを理解してないことにより、ハマる
asyncDataを使用していた
データをストアに入れてから表示させるため、fetchを使用する
fetchでapi通信する
ユーザー詳細
pages/_user/index.vue
// データをストアに入れてから表示させるため、fetchを使用する
// topページからデータをストアに格納→"そのデータを元に詳細データを取得・storeに格納→storeのデータを表示する"の流れ
fetch: async function() {
this.$store.commit("loading/setLoading", true)
let clickedFileUserId = ''
// 配列でclickedFileUserId取得
this.$store.getters['musicFiles/musicFileData'].forEach(musicFiledatum => {
clickedFileUserId = musicFiledatum.clickedFileUserId
});
await this.$store.dispatch('musicFiles/userDetailPageData', {
clickedFileUserId: clickedFileUserId,
})
this.$store.commit("loading/setLoading", false)
this.followedId = this.$store.getters['musicFiles/followedId']
this.userDetailItems = this.$store.getters['musicFiles/userDetailItems']
},
ファイル詳細
pages/_user/_title.vue
// データをストアに入れてから表示させるため、fetchを使用する
// topページからデータをストアに格納→"そのデータを元に詳細データを取得・storeに格納→storeのデータを表示する"の流れ
fetch: async function() {
this.$store.commit("loading/setLoading", true)
let clickedFileUserId = ''
// 配列でclickedFileUserId取得
this.$store.getters['musicFiles/musicFileData'].forEach(musicFiledatum => {
clickedFileUserId = musicFiledatum.clickedFileUserId
});
let clickedFileId = ''
this.$store.getters['musicFiles/musicFileData'].forEach(musicFiledatum => {
clickedFileId = musicFiledatum.clickedFileId
});
await this.$store.dispatch('musicFiles/musicDetailPageData', {
clickedLoginUserId: this.$store.state.auth.user.id,
clickedFileId: clickedFileId,
clickedFileUserId: clickedFileUserId,
})
this.$store.commit("loading/setLoading", false)
this.followedId = this.$store.getters['musicFiles/followedId']
this.userId = this.$store.getters['musicFiles/userId']
this.commentInfos = this.$store.getters['musicFiles/commentInfos']
},
おまけ
createdでも行けそうだが
created
Vueインスタンスが初期化されたあと、データも初期化されたときに呼ばれる
dataへのデータ挿入等に使用する
参考
Discussion