Would anyone have a hint as to why localData updates properly, while storeData remains stuck at -1 in this Vue SFC playground??
Reactivity issue with computedAsync
The entire code is below; the real use case involves REST calls which are mocked here using await timeout(3000);
If I use localData and storeData directly in the template both update fine. If I go through the computeds however only the local data updates.
Interestingly enough if I use both storeData and computedStoreData in the template they both update fine.
<template>
<h2>Test data from local: {{ computedLocalData }}</h2>
<h2>Test data from store: {{ computedStoreData }}</h2>
</template>
<script lang="ts" setup>
import {computedAsync} from "@vueuse/core";
import {computed, reactive, ref, type Ref, unref} from "vue";
const storeData = getTestData(3);
const computedStoreData = computed(() => storeData.value)
const localData = ref(-1);
const computedLocalData = computed(() => localData.value)
setTimeout(() => localData.value = 3, 2000)
// Store
const _testDatas = reactive<Record<number, Ref<number>>>({});
function timeout(ms : number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function getTestData(venueId : number) {
return computed(() => {
if (! (venueId in _testDatas)) {
_testDatas[venueId] = computedAsync(async () => {
await timeout(3000);
return venueId
}, -1, {lazy: false});
}
return unref(_testDatas[venueId]);
})
}
</script>
Edit: Even more interesting, adding this line makes it work:
watch(storeData, () => {})
[Edit 2]: Maybe I should explain why I ended up with trying to dynamically create computed composables. I have a dynamic set of venues that are obtained from the server:
venues = await fetchVenues()
Each venue then has a set of services:
venueServices = await fetchServices(venueId)
My components need the services for a venue, where the venue can be either static, or picked by the user, or supplied as the prop of a custom web component.
Obviously I want any given fetchServices call to happen at most once throughout the SPA for a given venue, and only if needed. I have tried several patterns but I can't come up with a robust working solution.
I found a slightly different approach that seems to work (pseudo-code since I edited it to simplify):