My project is created using Vue, Vite and Pinia. I used options api for communication in my project. I want to know the tips that I should follow to never face this problem so that I can always use it as a pattern in my code.
Song.vue:127 Uncaught ReferenceError: Cannot access 'useMusicStore' before initialization
at Song.vue:127:17
this is my Song.vue componnent:
this is my template tag:
<template>
<!-- Music Header -->
<section class="w-full mb-8 py-14 text-center text-white relative">
<div
class="absolute inset-0 w-full h-full box-border bg-contain music-bg"
style="background-image: url(/assets/img/song-header.png)"
></div>
<div class="container mx-auto flex items-center">
<!-- Play/Pause Button -->
<button @click.prevent="playMusic(music)"
type="button"
class="z-50 h-24 w-24 text-3xl bg-white text-black rounded-full focus:outline-none"
>
<i class="fas" :class="{'fa-play': !playing, 'fa-pause': playing}"></i>
</button>
<div class="z-50 text-left ml-8">
<!-- Song Info -->
<div class="text-3xl font-bold">{{music.displayName}}</div>
<div>{{music.gener}}</div>
</div>
</div>
</section>
<!-- Form -->
<section class="container mx-auto mt-6">
<div
class="bg-white rounded border border-gray-200 relative flex flex-col"
>
<div class="px-6 pt-6 pb-5 font-bold border-b border-gray-200">
<!-- Comment Count -->
<span class="card-title">Comments ({{music.commentCount}})</span>
<i class="fa fa-comments float-right text-green-400 text-2xl"></i>
</div>
<div class="p-6" v-show="userLoggedIn">
<!--Comment Message Box-->
<div class="text-white text-center font-bold p-4 rounded mb-4"
v-if="comment_show_alert" :class="comment_alert_variant">
{{ comment_alert_msg}}
</div>
<!--Comment Form-->
<vee-form @submit="postComment">
<vee-field
type="textarea"
name="comment"
class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded mb-4"
placeholder="Your comment here...">
</vee-field>
<error-message name="comment" class="text-red-600"></error-message>
<button
:disabled="comment_in_submission"
type="submit"
class="py-1.5 px-3 rounded text-white bg-green-600 block"
>
Submit
</button>
</vee-form>
<!-- Sort Comments -->
<select v-model="sort"
class="block mt-4 py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
>
<option value="cratedAt" selected>Latest</option>
<option value="-cratedAt">Oldest</option>
</select>
</div>
</div>
</section>
<!-- Comments -->
<ul class="container mx-auto">
<CommentItem v-for="comment in comments"
:key="comment._id"
:comment="comment"
/>
</ul>
</template>
and this is my script tag:
<script>
import useMusicStore from '@/stores/music.js'
import useCommentStore from '@/stores/comment.js'
import useUserStore from '@/stores/user.js'
import usePlayerStore from '@/stores/player.js'
import CommentItem from './base/CommentItem.vue'
import {mapState, mapActions, mapWritableState} from "pinia";
import { ErrorMessage, Field, Form } from 'vee-validate'
export default {
data(){
return {
commentSchema:{
comment: 'required|min:8|max:10',
},
sort:'cratedAt'
}
},
name: 'Song',
components: {
ErrorMessage,
Field,
Form,
CommentItem
},
created(){
this.musicStore = useMusicStore(); // initialize musicStore in created lifecycle hook
this.fetchMusic(this.$route.params.songId)
this.fetchComments(this.$route.params.songId, this.sort)
},
computed:{
musicStore(){
return useMusicStore()
}
,
music(){
return this.musicStore.music
},
...mapWritableState(useCommentStore, [
'comments',
'commentBoxMsg',
'comment_show_alert',
'comment_alert_variant',
'comment_alert_msg',
'comment_in_submission'
]),
...mapState(useUserStore, ['userLoggedIn']),
...mapState(useMusicStore, ['playing'])
},
methods:{
...mapActions(useCommentStore, {getCommentsByMusicId: "getCommentsByMusicId"}),
...mapActions(useCommentStore, {createComment: "createComment"}),
...mapActions(usePlayerStore, {playMusic: "playMusic"}),
async fetchMusic(songId){
try {
await this.musicStore.getOneMusic(songId)
}catch(error){
console.log('Error fetching music', error)
}
},
async fetchComments(songId, sortBy){
try {
await this.getCommentsByMusicId(songId, sortBy)
}catch(error){
console.log('Error fetching comments', error)
}
},
async postComment(values){
this.comment_in_submission = true
try{
console.log(values)
let reqBody = {
music: this.music._id
}
reqBody.comment = values.comment
console.log(reqBody)
await this.createComment(reqBody)
}catch(error){
console.log('Error creating comment', error)
}finally {
this.comment_in_submission=false
this.comment_show_alert = false
}
}
},
watch:{
sort(){
this.fetchComments(this.$route.params.songId, this.sort)
}
}
}
</script>
I fixed this problem.
I define a computed property instead of using mapState()
.
computed:{
musicStore(){
return useMusicStore()
}
,
music(){
return this.musicStore.music
},
...mapWritableState(useCommentStore, [
'comments',
'commentBoxMsg',
'comment_show_alert',
'comment_alert_variant',
'comment_alert_msg',
'comment_in_submission'
]),
// ...mapState(useMusicStore, ['playing'])
playing(){
return this.musicStore.playing
},
...mapState(useUserStore, ['userLoggedIn']),
}