My goal is to load an item into a child component for editing purposes. The approach I am taking involves passing an itemId
from the parent to the child as a prop. In the child component, I use the function store.itemForId(id)
to fetch the itemData from a vueFire/firestore collection. While I can successfully retrieve the item document in the child component, it loses reactivity. If there are external updates made to the firestore Document, the collection in the pinia store and the data in the parent get updated, but the item retrieved in the child component does not reflect these changes.
However, when I use the same function in the parent component and pass the item down to the child, the reactivity is maintained. Although this workaround works temporarily, it doesn't fully solve my problem as I eventually need the ability to edit the item. This makes me suspect that the issue lies within the child component itself.
In my setup, I have a pinia store that contains a projectItems
Collection and a projectInfo
Document. The projectInfo.itemOrder
specifies the display order for the items.
The code snippet below shows an excerpt from 'projectStore.js' where the main logic resides:
// projectStore.js
const projectInfo = useDocument(() => doc(db, projectPath))
const { data:projectItems, promise:itemsPromise } = useCollection(() => collection(db, itemsPath))
function itemForId(id) {
return projectItems.value.find((item) => item.id === id)
}
A snippet of 'MyParent.vue' illustrates how I'm handling the data flow:
<script setup>
import { useProjectStore } from 'stores/projectStore'
const projectStore = useProjectStore()
const { projectInfo, projectItems } = storeToRefs(projectStore)
</setup>
<template>
<div>Child receives Id, but it's not reactive</div>
<template v-for="itemId in projectInfo.itemOrder" :key="itemId">
<IdChild :itemId="itemId" />
</template>
<div>Child receives Item, and it remains reactive</div>
<template v-for="itemId in projectInfo.itemOrder" :key="itemId">
<ItemChild :item="projectStore.itemForId(itemId)" />
</template>
<div>Raw Item Data, which is reactive</div>
<div>{{ projectItems }}</div>
</template>
'IdChild.vue' demonstrates the non-reactive behavior:
<script setup>
import { useProjectStore } from 'stores/projectStore'
const props = defineProps({ itemId: String })
const projectStore = useProjectStore()
const { projectItems } = storeToRefs(projectStore)
const item = ref(projectStore.itemForId(props.itemId))
</setup>
<template>
<div>{{ item.name }}, but it's not reactive</div>
<!-- This approach is reactive but seems repetitive -->
<div>{{ projectStore.itemForId(itemId).name }}</div>
<div>Raw Item Data, intended for troubleshooting but also reactive</div>
<div>{{ projectItems }}</div>
</template>
'ItemChild.vue' was created for troubleshooting purposes and is reactive but lacks editability due to receiving the item as a prop:
<script setup>
import { useProjectStore } from 'stores/projectStore'
const props = defineProps({ item: Object })
</setup>
<template>
<div>{{ item.name }}, reactive</div>
</template>
I am seeking solutions on how to ensure reactivity with the item
within my child components or insights into any nuances regarding reactivity that I might be overlooking.