I have two variables in my userStore.js
, userData
which is populated by the object returned by the login function and profileData
which I populate with data from firestore using a VueFire composable inside the getUserData
function.
VueDevTools shows that both variables are populated correctly with all the expected values.
The problem is that in my template I can render data from the userData
variable but can't render data from the profileData
variable but I can't understand why.
The console show no errors but it throws me this warning about the profileData.value
declaration line: [Vue warn]: inject() can only be used inside setup() or functional components.
This is my userStore.js
export const useUserStore = defineStore("UserStore", () => {
...
const userData = ref({});
const profileData = ref({});
async function login() {
await signInWithEmailAndPassword(auth, this.email, this.password)
.then((userCredential) => {
userData.value = userCredential.user;
getUserData(userCredential.user.uid);
})
.catch((error) => {
const errorCode = error.code;
console.log(errorCode);
errorMessage.value = error.message;
alert(errorMessage.value);
});
}
async function getUserData(uid) {
profileData.value = useDocument(doc(collection(db, "users"), uid), {
once: true,
});
}
return {
userData,
profileData,
login
};
});
This is my SFC
<template>
<aside
<div>
<div><p>{{userData.profileData.fullName}}</p></div> <-- This line shows nothing
<div><p>{{userData.userData.email}}</p></div> <-- This line renders correctly
</div>
</aside>
</template>
<script setup>
import { ref } from "vue";
import { useUserStore } from "../stores/userStore.js";
const userData = useUserStore();
</script>
Your userStore.js
seems correct, but make sure that profileData
is initialized as null
or an empty object, and you're updating it properly when the document is retrieved from Firestore.
export const useUserStore = defineStore("UserStore", () => {
const userData = ref(null);
const profileData = ref(null); // initialized as null to handle loading state
Also, add optional chaining (?.)
to ensure that if profileData
is not yet populated, it won't throw an error. This should render correctly now.
<template>
<aside>
<div>
<div><p>{{ profileData.value?.fullName }}</p></div>
<div><p>{{ userData.userData.email }}</p></div>
</div>
</aside>
</template>
</body></html>
The reason why you are not seeing any error in console is because you have defined profile data as an object, and when we try to access any non existing property of object, we don't get an error but get undefined
. See below code for your understanding.
const obj = {
name: 'Test'
}
console.log(obj.name) // This will print 'Test'
console.log(obj.something) // This will print undefined because something is not present
console.log(obj.something.try) // This will give error, because we are trying to access try property of something, where something is undefined and we cannot access propety of undefined