N
Nuxt3mo ago
Gregor

[useFetch] Component is already mounted, please use $fetch instead.

Hi,
I am using useFetch to load a product on the server side once... works fine, but the user can change the region and then price/taxe change, so the product has to be reloaded. this causes this error... Should I just duplicate the function and rename it to reFetchProduct and use $fetch or are there other solutions for this use case?
async getProduct(handle) {
const regionsStore = useRegionsStore();
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionsStore.regionId,
country_code: regionsStore.selectedRegion.countries[0].iso_2,
});
const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;
try {
const { data } = await useFetch(
`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

return data.value.products[0];
} catch (error) {
throw error;
}
},
async getProduct(handle) {
const regionsStore = useRegionsStore();
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionsStore.regionId,
country_code: regionsStore.selectedRegion.countries[0].iso_2,
});
const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;
try {
const { data } = await useFetch(
`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

return data.value.products[0];
} catch (error) {
throw error;
}
},
11 Replies
manniL
manniL3mo ago
how do you call getProduct is the interesting question
manniL
manniL3mo ago
Alexander Lichter
YouTube
You are using useFetch WRONG! (I hope you don't)
💪🏻 useFetch is a mighty composable to fetch data in your Nuxt.js application. It can do so many things, from updating state to refreshing calls easily and even data caching is possible. But often I see that people misuse useFetch because it is so tempting to use all the features, even when you shouldn't. In this video I show the most common mist...
Gregor
GregorOP3mo ago
in the product page I call this action from my pinia store
const fetchProduct = async () => {
await productsStore.getProduct(route.params.product);
};
//initial load
const product = ref(await fetchProduct());

// on region change reload product
watch(regionId, async () => {
product.value = await fetchProduct();
});
const fetchProduct = async () => {
await productsStore.getProduct(route.params.product);
};
//initial load
const product = ref(await fetchProduct());

// on region change reload product
watch(regionId, async () => {
product.value = await fetchProduct();
});
manniL
manniL3mo ago
getProduct should be a composable and called as one but you are using it inside a "normal" function, causing the problem See the video above 👍
Gregor
GregorOP3mo ago
just watching 😉 thanks for the video 😉 my composable looks like this. I have only the problem that the url is no more reactive...
export default function useGetProduct() {
const route = useRoute();
const handle = route.params.product;
const regionsStore = useRegionsStore();
const { regionId, countryCode } = storeToRefs(regionsStore);

const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
});
//tried a function as well
const getQueryParams = () => {
return new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
}).toString();
};

const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;

const { error, data, refresh } = useFetch(
`http://localhost:9000/store/products?handle=${handle}&${getQueryParams()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

const getProduct = async () => {
//values gets uodated
console.log(regionId.value, countryCode.value);
console.log(getQueryParams());
await refresh();
if (error.value) {
console.error("error", error.value);
} else {
return data.value.products[0];
}
};
return { getProduct };
}
export default function useGetProduct() {
const route = useRoute();
const handle = route.params.product;
const regionsStore = useRegionsStore();
const { regionId, countryCode } = storeToRefs(regionsStore);

const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
});
//tried a function as well
const getQueryParams = () => {
return new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
}).toString();
};

const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;

const { error, data, refresh } = useFetch(
`http://localhost:9000/store/products?handle=${handle}&${getQueryParams()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

const getProduct = async () => {
//values gets uodated
console.log(regionId.value, countryCode.value);
console.log(getQueryParams());
await refresh();
if (error.value) {
console.error("error", error.value);
} else {
return data.value.products[0];
}
};
return { getProduct };
}
Do you have any idea how I can get around this?
manniL
manniL3mo ago
because you lose reactivity, yes. https://www.youtube.com/watch?v=sccsXulqMX8
Alexander Lichter
YouTube
Avoid losing Reactivity in your Vue Application
🔄 Reactivity is a crucial and and concept when building any kind of Vue application. But especially with the Composition API, I see more and more people having trouble with Reactivity and ensure that the "reactivity chain" will be kept up throughout various composables and components. In this video, I want to highlight typical issues with ref's ...
manniL
manniL3mo ago
😄
Gregor
GregorOP3mo ago
hmm understood, but also not understood in my case 😂 tried to make the whole object reative...
const params = reactive({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
});

const queryParams = new URLSearchParams(params);

useFetch(`http://localhost:9000/store/products?handle=${handle}&${queryParams.value.toString()}`,
...
const params = reactive({
fields: `*variants.calculated_price`,
region_id: regionId.value,
country_code: countryCode.value,
});

const queryParams = new URLSearchParams(params);

useFetch(`http://localhost:9000/store/products?handle=${handle}&${queryParams.value.toString()}`,
...
and also this with getter
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: () => regionId.value,
country_code: () => countryCode.value,
});

useFetch(`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
...
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: () => regionId.value,
country_code: () => countryCode.value,
});

useFetch(`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
...
but no success...
manniL
manniL3mo ago
params should be a computed And you can use the params option of useFetch instead of passing it like you do rn
Gregor
GregorOP3mo ago
thanks works perfect now 😉 and with params option is much better to read, thanks alot 😉
manniL
manniL3mo ago
you are welcome 👏
Want results from more Discord servers?
Add your server