Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PayloadExtraction/useFetch persists data when it shouldn't #22348

Open
madsh93 opened this issue Jul 26, 2023 · 11 comments
Open

PayloadExtraction/useFetch persists data when it shouldn't #22348

madsh93 opened this issue Jul 26, 2023 · 11 comments

Comments

@madsh93
Copy link

madsh93 commented Jul 26, 2023

Environment


  • Operating System: Linux
  • Node Version: v16.20.0
  • Nuxt Version: 3.6.5
  • Nitro Version: 2.5.2
  • Package Manager: yarn@1.22.19
  • Builder: vite
  • User Config: devtools, experimental, nitro
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/github-4ym9i1?file=pages%2F%5Bid%5D%2Findex.vue

Describe the bug

To reproduce:

  1. yarn run build
  2. node .output/server/index.mjs
  3. Go to a product and select a size
  4. Go back
  5. Go to same product as in step 3

You'll then see the size is not the default size.

Additional context

No response

Logs

No response

@stackblitz
Copy link

stackblitz bot commented Jul 26, 2023

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

@madsh93 madsh93 changed the title PayloadExtraction persists data when it shouldn't PayloadExtraction/useFetch persists data when it shouldn't Jul 27, 2023
@danielroe
Copy link
Member

You should use route.fullPath as the key rather than route.path if query params are significant to the return value of the asyncData fetcher.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale Jul 27, 2023
@madsh93
Copy link
Author

madsh93 commented Jul 29, 2023

Not sure how to reopen this. The issue is not fixed by setting route.fullPath or removing the key entirely.

@94726
Copy link
Contributor

94726 commented Jul 31, 2023

This isn't exactly related to #22277, but they do share some problems.

Setting a specific key doesn't really help in this situation, as it's usually going to have the same value. Because routing using query-params doesn't change the component instance, the asyncData key won't update unless actually switching the route. Also when going back and clicking on the same product, there are again no query-params so it's the same key.


But to explain why this is only happening when using payloadExtraction, I broke down what happens at each step of your reproduction:

  1. Go to a product
    3.1. select a size
    This will trigger the watch and fetch a new product with that size. (always skips getCachedData() because of _initial isn't true
    The result of that fetch updates asyncDatas data
  2. Go back
  3. Go to same product as in step 3
    _initial is true
    hasCachedData() is true (payload extracted data in nuxt.static.data[key]
    Therefore we skip fetching new data because of
    if ((opts._initial || (nuxt.isHydrating && opts._initial !== false)) && hasCachedData()) {
    return getCachedData()
    }

    But because we skipped creating a new promise, the previous asyncDataPromise is returned, which still has the old data.
    const asyncDataPromise = Promise.resolve(nuxt._asyncDataPromises[key]).then(() => asyncData) as AsyncData<ResT, DataE>
    Object.assign(asyncDataPromise, asyncData)
    return asyncDataPromise as AsyncData<PickFrom<DataT, PickKeys>, DataE>

The getCachedData() would actually have the correct value, but the return statement doesn't control the data value of asyncData. Instead, something like the following would be necessary.

 if ((opts._initial || (nuxt.isHydrating && opts._initial !== false)) && hasCachedData()) {
+  asyncData.data.value = getCachedData()
   return getCachedData() 
 } 

@Gruce
Copy link

Gruce commented Aug 7, 2023

Have the exact same problem.

@madsh93
Copy link
Author

madsh93 commented Aug 7, 2023

Thank you for your analysis @94726 hopefully this can get resolved. I haven't met many who has run into this issue, which makes me think I'm following bad practice. Do you have any idea if this is in fact so? From my point of view this is a basic way of fetching.

@94726
Copy link
Contributor

94726 commented Aug 9, 2023

@madsh93 to me, the general usecase in your reproduction seems very resonable. I can see myself and others trying something similar when working with paginated queries, for example.

But now that I think about it, while this issue is likely a bug, it might be highlighting a missing feature too.
This problem could also be solved by allowing dynamic keys like this:

useAsyncData(() => route.fullPath, () => $fetch(...))

Most usecases of the watch option would probably benefit from using the watched values as (additional) keys.

@Sandros94
Copy link

@madsh93 to me, the general usecase in your reproduction seems very resonable. I can see myself and others trying something similar when working with paginated queries, for example.

But now that I think about it, while this issue is likely a bug, it might be highlighting a missing feature too. This problem could also be solved by allowing dynamic keys like this:

useAsyncData(() => route.fullPath, () => $fetch(...))

Most usecases of the watch option would probably benefit from using the watched values as (additional) keys.

Something that I had in mind when opening #23000

@madsh93
Copy link
Author

madsh93 commented Nov 21, 2023

Can confirm this still does not work in 3.8.1

@manniL
Copy link
Member

manniL commented Nov 25, 2023

Interesting issue. I've used

const { data: product } = await useFetch('/api/product', {
  key: route.fullPath,
  params
})

And locally it works (with build) - but not in stackblitz 🙈
Can you check if that's the case for you too?

weird-behavior-usefetch-payload.webm

@madsh93
Copy link
Author

madsh93 commented Nov 26, 2023

Hey @manniL

Thanks for taking a look. Interesting that it works for you locally on build. In my case it doesn't. I've used your example with useFetch and still on nuxt 3.6.5 (also tested with 3.8.2 with same result) as in the repo I provided. I'm on node v18.17.1

CleanShot 2023-11-26 at 13 32 10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants