Closed SDIjeremy closed 7 months ago
Hey @SDIjeremy, are you talking about this particular method from your gist?
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chatsBroken`, async () => {
await new Promise(resolve => { setTimeout(resolve, 5); });
// Doing any other async action breaks this ....
return await fetchSanctum(`https://jsonplaceholder.typicode.com/posts`);
});
Hey @SDIjeremy, are you talking about this particular method from your gist?
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chatsBroken`, async () => { await new Promise(resolve => { setTimeout(resolve, 5); }); // Doing any other async action breaks this .... return await fetchSanctum(`https://jsonplaceholder.typicode.com/posts`); });
Yes! For example I have to first fetch an ID/Slug from the Laravel API then pass that ID/Slug in the following request for all the posts. But no matter how I do it (with fetchSanctum
) I get that composable error.
The weirdest thing also, is that if I make that first request I need somewhere else (in a Middleware) and have that data then it works fine.
Working:
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chats`, async () => {
const [ post ] = await $fetch('https://jsonplaceholder.typicode.com/posts');
return await $fetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`);
});
Not Working:
const sanctumFetch = useSanctumClient();
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chats`, async () => {
const [ post ] = await sanctumFetch('https://jsonplaceholder.typicode.com/posts');
return await sanctumFetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`);
});
In these cases it is ~not throwing the error about composables, but instead~ not returning any date in the case of useSanctumClient
.
Edit: if you put a try catch around the second sanctumFetch
, it will log the the error about composables.
Working
<script setup lang="ts">
definePageMeta({
middleware: [
'sanctum:auth',
]
})
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chats`, async () => {
const [post] = await $fetch('https://jsonplaceholder.typicode.com/posts');
console.log('post', post);
const comments = await $fetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`);
console.log('comments', comments);
return comments;
});
console.log(data.value);
</script>
<template>
<section>
<div class="container">
<h1>Profile</h1>
<pre>{{ data }}</pre>
</div>
</section>
</template>
Not Working
<script setup lang="ts">
definePageMeta({
middleware: [
'sanctum:auth',
]
})
const sanctumFetch = useSanctumClient();
const { data, error }: { data: Ref, error: Ref } = await useAsyncData(`chats`, async () => {
const [post] = await sanctumFetch('https://jsonplaceholder.typicode.com/posts');
console.log('post', post); // this outputs
const comments = await sanctumFetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`);
console.log('comments', comments); // this is null, never runs
return comments;
});
console.log(data.value);
</script>
<template>
<section>
<div class="container">
<h1>Profile</h1>
<pre>{{ data }}</pre>
</div>
</section>
</template>
I'm thinking this is an SSR issue when using multiple sanctumFetch
. Because when you navigate from one page to the page above, the data displays properly. But if you refresh the page, then there is no data in the case when using sanctumFetch
, but it is working with $fetch
.
Edit: even more specifically an issue when using useAsyncData
as both codes above work outside of it.
Edit2: the composable error only seems to happen from within the Pinia action when there is more than one sanctumFetch
inside the function, wether it is encased in a useAsyncData
or not.
thanks a lot @SDIjeremy for such a detailed reply 👍 it looks like a rare case to me, but it might be the same problem we can face inside of the module when we have multiple calls on the same Nuxt app, here are more details about it. I will try to take a closer look on the weekend.
I think that might be the wrong link @manchenkoff 🙃
For now I will stick with ssr: false
until we can resolve this.
I think that might be the wrong link @manchenkoff 🙃
Ooops 😄 updated
For now I will stick with ssr: false until we can resolve this.
Okay, I will let you know once I find the solution
any luck on this? would love to have SSR working again. I think maybe this could be more of a Nuxt issue?
Hey @SDIjeremy, nope, no luck at all, the only thing I confirmed is that it doesn't happen with multiple calls if you use Promise.all()
with several useAsyncData
inside. Multiple calls of sanctum client w/o this composable also don't affect the behavior but when it comes to useAsyncData
with multiple calls inside - it fails with this error. I believe this is some sort of Nuxt internal scope magic 😄
Right now I am unsure about a possible solution, but I will check the sources of Nuxt composable to find a reason and will try to update this issue once I have something.
Hey @SDIjeremy, nope, no luck at all, the only thing I confirmed is that it doesn't happen with multiple calls if you use
Promise.all()
with severaluseAsyncData
inside. Multiple calls of sanctum client w/o this composable also don't affect the behavior but when it comes touseAsyncData
with multiple calls inside - it fails with this error. I believe this is some sort of Nuxt internal scope magic 😄Right now I am unsure about a possible solution, but I will check the sources of Nuxt composable to find a reason and will try to update this issue once I have something.
Can you share the example for this so I can try it locally?
Can you share the example for this so I can try it locally?
Sure thing, I used something like this
const sanctumFetch = useSanctumClient();
async function initStoreOne() {
const { data, error } = await useAsyncData(() => sanctumFetch('/api/one'));
// process data and store results somewhere
}
async function initStoreTwo() {
const { data, error } = await useAsyncData(() => sanctumFetch('/api/two'));
// process data and store results somewhere
}
const tasks = [initStoreOne, initStoreTwo];
await Promise.all(tasks);
The code example was changed a bit because I used it for two separate Pinia store initialization functions that use useSanctumClient
to load data during the first app run.
But when it comes to several calls inside of one useAsyncData
, then it generates a warning, like in the examples above
Hey @SDIjeremy, I have a small update here 😄
So, after some investigation, I can confirm that the problem is related to the Nuxt app instance which is reset after the first call inside of useAsyncData
and since my plugin client depends on it to collect cookies for sending to the API - it fails. I also noticed that it fails only on SSR mode while CSR can do everything w/o any issue 🤔
Here you can find more details about this instance reset operation - Nuxt docs.
Anyway, it looks like they have a solution that I had a chance to test and didn't get any error in both CSR/SSR modes. Here it is - asyncContext.
I've used this code to test it
const response = await useAsyncData(async () => {
try {
const user1 = await client('/api/user');
console.log('User loaded [1/2]', user1);
const user2 = await client('/api/user');
console.log('User loaded [2/2]', user2);
return user2;
} catch (e) {
console.error(e);
}
});
As a result, with asyncContext
I got no errors while w/o it Nuxt still shows that warning.
I'm closing this for now, feel free to reopen if there are some issues!
@manchenkoff amazing research!! I will try it myself!!
I'm not really sure the best way to make a shareable reproduction for this, but I'm running into a very very strange problem, and it seems related to the
useSanctumClient
...Within
useAsyncData
, if you use any other await then I get the below error. Even if I put twofetchSanctum
s in different places within the same function, it seems to have problems. This isn't the case when using$fetch
withinuseAsyncData
.https://gist.github.com/SDIjeremy/e86c2d33483aff7f89ddc85af6a9f1fc