I'm working on a website that uses vue and firebase. After the authentication part the user gets to the dashboard where there is the list of his projects that are a subcollection of the user document in firestore. I made a pinia store that manages this data and each time a project is created with the form or gets deleted the state.projects updates with the new array of projects that gets cycled to display the list in the view. Inside the view I have access to the store.projects thanks to a getter that should be reactive but when I add or delete a project nothing happens in the view, but still the state.projects gets updated.
here is the code of the DashboardView.vue:
<template>
<MainHeader mode="dashboard" />
<main >
<div >
<section >
<div >
<h1 >Projects</h1>
<!-- <TextInput type="text" placeholder="Search" v-model="filter" /> -->
</div>
<div >
<ul >
<li
v-for="project in projects"
:key="project.id"
>
{{ project.id }}
<!-- <router-link
:to="{ name: 'ProjectView', params: { id: project.id} }">
</router-link> -->
<SimpleButton @click="deleteProject(project.id)" type="button" text="delete" />
</li>
</ul>
</div>
<div >
<form @submit.prevent="createProject">
<TextInput type="text" placeholder="name" v-model="form.id" />
<TextInput type="text" placeholder="website" v-model="form.website" />
<SimpleButton type="submit" text="Add" />
</form>
</div>
</section>
</div>
</main>
</template>
<script>
import { useUserDataStore } from "../stores/UserDataStore.js";
import MainHeader from "../components/MainHeader.vue";
import SimpleButton from "../components/SimpleButton.vue";
import TextInput from "../components/TextInput.vue";
import { ref } from '@vue/reactivity';
export default {
name: "DashboardView",
components: {
MainHeader,
SimpleButton,
TextInput,
},
setup() {
// const filter = "";
const form = ref({});
const userDataStore = useUserDataStore();
const projects = userDataStore.getProjects;
const createProject = () => {
userDataStore.createProject(form.value)
}
const deleteProject = (id) => {
userDataStore.deleteProject(id)
}
return {
projects,
form,
createProject,
deleteProject,
};
},
};
</script>
And here the pinia store code:
import { defineStore } from "pinia";
import router from "../router";
import { db } from '../firebase';
import { doc, setDoc, getDoc, getDocs, collection, deleteDoc } from 'firebase/firestore'
export const useUserDataStore = defineStore('UserDataStore', {
state: () => {
userData: { }
projects: []
uid: null
},
actions: {
createNewUser(uid, name) {
setDoc(doc(db, "users", uid), {
name
})
.then(() => {
this.fetchUserData(uid)
})
.catch((error) => console.log(error))
},
fetchUserData(uid) {
this.uid = uid
// Fetch user doc with uid
getDoc(doc(db, "users", uid))
.then((response) => {
this.userData = response.data()
// Fetch user projects
getDocs(collection(db, "users", uid, "projects"))
.then((response) => {
const projectsArray = []
response.forEach(el => {
projectsArray.push({ data: el.data(), id: el.id})
})
this.projects = projectsArray
console.log(this.projects);
router.push({ name: 'DashboardView' })
})
})
.catch((error) => console.log(error))
},
createProject(details) {
const { id, website } = details
setDoc(doc(db, "users", this.uid, "projects", id), {
website
}).then(() => {
console.log('created');
this.fetchUserData(this.uid)
})
.catch((err) => console.log(err))
},
deleteProject(id) {
deleteDoc(doc(db, "users", this.uid, "projects", id))
.then(() => {
console.log('deleted');
this.fetchUserData(this.uid);
})
.catch(err => console.log(err))
}
},
getters: {
getProjects: (state) => state.projects
}
})
CodePudding user response:
A store is reactive object, the reactivity of store property is disabled at the time when it's accessed in setup function:
const projects = userDataStore.getProjects;
It should be either:
const projects = computed(() => userDataStore.getProjects);
Or:
const { getProjects: projects } = storeToRefs(userDataStore);