Nuxt.js: Asyncdata and fetch called twice in nested route

Created on 29 Sep 2018  路  41Comments  路  Source: nuxt/nuxt.js

Version

v2.0.0

Reproduction

https://codesandbox.io/s/k0rj8844nv

Steps to reproduce

let's say I have the following structure:

pages\user\_id.vue
pages\user\_id\_name.vue

Note , in one _id is a file, in the other is folder

What is expected ?

only pages\user\_id\_name.vue should be rendered.

What is actually happening?

when I go to page /user/12/john
then I see asyncdata being called twice.

pages_user__id.js:xxx
pages_user__id__name.js:xxx

seems like both pages being rendered. Asyncdata is called on both, although created and mounted called once

Additional comments?

This might explain many other asyncdata multiple call issues

This bug report is available on Nuxt community (#c7867)
bug-report pending

Most helpful comment

I use nuxt 2.9.2 and a have the same issue. I can't resolve even with a Boolean solution. This issue cause big problems to me. If someone hava an workarround, please, tell me.

All 41 comments

@husayt Could you add a CodeSandBox for reproduction?

I was just playing around with that:
https://codesandbox.io/s/xl312qo8ow

If you browse to /user/12/john it shows the page for the _id.vue-file and asyncData gets called for both pages.

Thanks @Fubinator! We will look into it :relaxed:

Same goes for fetch.

Thanks @Fubinator , you did codesandbox, before I could come in

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

I found (maybe) same case on v2.3.4.
I avoided this problem that I moved 'computed' variable in component to 'method'.

is also called multiple times in this structure
example sandbox : https://codesandbox.io/embed/w04l29nmm7
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

hello, What can be expected to solve this problem?

Hello you can use custom routes to solve this problem.

in nuxt.config.js file

 router: {
    extendRoutes(routes, resolve) {
      routes.push({
        name: 'category',
        path: '/:category',
        component: resolve(__dirname, 'pages/category/category.vue')
      })
      routes.push({
        name: 'category-city',
        path: '/:category/:city',
        component: resolve(__dirname, 'pages/category/category.vue')
      })
    }
  },

Hi @manniL , I also can confirm this bug happen in our production site. (SSR)

But there was also some undefined behavior that we noticed.

The code that we use in our fetch method is look like this,

async fetch({ store, params }) {
    await store.dispatch('episode/fetchItemBySlug', params.slug)
    await store.dispatch('episode/fetchArticlesLatestBySlug', params.slug) // latest
    await store.dispatch('episode/fetchArticlesPopularBySlug', params.slug) // popular
}

We want to refactor so that we can fetch latest and popular into the browser part of the site.

When I remove the two last line of code, somehow the second fetch will returning params.slug as 'undefined'. This in return will break the server side of the code. And the second fetch is also happening randomly, there is no consistency of the occurrences. The only consistency that I get is that when the three await line is intact, the params.slug will not return undefined.

There might be some connection with the store part, since that definitely get reset the when the second fetch is happening. And second fetch not happening when I have two of those three await line intact.

My pages structure is look like this :

--| pages
----| episode
------| _slug

and custom routes solution (above) didn't fix it.

Got update, change my store action code into proper async await and return it properly will make the second fetch not happening.

@dimassrio could you share a code example of what exactly help you resolve an issue?
I use regular async fetch like

async fetch({store, params, query}) {
console.log('params.slug:', params.slug)
}

where is params.slug gives me undefined during SSR phase than it's called the second time on the client

Can confirm this is still an issue in v2.10.0. "Returning" any axios calls directly from methods seems to help a bit, but additional "undefined" calls are still being made.

UPDATE: I was able to fix this issue entirely by turning off my global event bus in a beforeDestroy() hook.

beforeDestroy() {
    this.$bus.$off()
},

Not sure how the two are related but give this a shot if you have components that are listening for global events and are making AJAX calls as a result of those events. I setup my global event bus per this article: https://binbytes.com/blog/create-global-event-bus-in-nuxtjs

I don't use any event bus but still have this issue

I double checked my current setup, I have this route structure:
--| pages
----| manufacturer
------| _slug
---------| products.vue
So the fetch() function is called once on the server and it's correct behavior, but on the client it's called 3 times! And it's happening like that for all my nested routes. I'm using Nuxt 2.9.2
The only workaround I could imagine was adding a boolean switcher fetched that is false by default and wrap all of my fetch() logic behind this flag:

let fetched = false
  export default {
    async fetch({store, params, query}) {
      console.log('Products fetch') // Is called 3 times
      if(params.slug && !fetched) {
          fetched = true
          ......
      }

any updates about this issue? this happens in my environment as well with [email protected]. my nuxt environment uses custom routings and nested routes, and asyncData and fetch are called twice even on a page doesnt have nested routes.

this makes load average higher and it can be problem for my service... :(

Same here Nuxt 2.11. Oddly this didn't happen the last time I worked on this project back in October. I had to put it aside and hadn't touched it until today, when I updated a few packages including Nuxt and suddenly it's firing Fetch multiple times (three in my case). The only thing that worked for me was using AndrewBogdanovTSS's approach with async and a boolean. I'm using custom routes with the router.extendedRoutes parameter in nuxt.config.js because my app only has one real view shared by many routes:

router: {
extendRoutes(routes, resolve) {
routes.push(
{
name: "event-list",
path: "/",
component: resolve(__dirname, "pages/PageEventsList.vue")
},
{
name: "event-landing",
path: "/:event",
component: resolve(__dirname, "pages/PageEvent.vue")
},
{
name: "event-section",
path: "/:event/:section",
component: resolve(__dirname, "pages/PageEvent.vue")
},
{
name: "event-panel",
path: "/:event/:section/:panel",
component: resolve(__dirname, "pages/PageEvent.vue")
},
{
name: "event-subpanel",
path: "/:event/:section/:panel/:subpanel",
component: resolve(__dirname, "pages/PageEvent.vue")
},
{
name: "event-post",
path: "/:event/:section/:panel/:subpanel/:post",
component: resolve(__dirname, "pages/PageEvent.vue")
}
);
}
},

@thomascallahandell be careful with my solution since it's not a silver bullet and has it's downsides. Check that everything works well with navigating back and forth between routes since this boolean value can be stored in memory and not updated properly when navigation occures.

Very annoying issue... I can't even get that Boolean solution to work

@AndrewBogdanovTSS I think it works for me because I never actually change the root component (where the feth() call is) no matter how the routes change. All of my routes point to the same component and it's named and keyed so it doesn't ever reload. But you're right, it's hardly a solution, I can still see it attempting to make those additional calls to fetch(), so while it "works" it's definitely not "fixed".

I use nuxt 2.9.2 and a have the same issue. I can't resolve even with a Boolean solution. This issue cause big problems to me. If someone hava an workarround, please, tell me.

I have the same issue using asyncData, while using params, but I realized the second time, params is undefined, so I just rap my entire code inside a params != undefined if statement.

@dubem-kizito they might not always be undefined so your check can fail from time to time. But the main issue here is that basically params should never be undefined but they are and I don't understand why

I have same problem on structure:

catalog
    _category
        index.vue
        _.vue
    _category.vue
    index.vue

asyncData in _.vue component called multiple times.

For me, this happens when I use keep-alive and keep-alive-props. Discarded the keep-alive-props, the issue is resolved.

Does disabling it have any side effects?

I'd used keep-alive-props to exclude some pages. It was not that tricky to do it in another way. I'm happy with the result; It is slightly more performant actually :)

I don't use keep-alive-props but still have this issue

Anyone else using the Vuetify Module and experiencing this bug?

I removed all the plugins/modules one by one and found out I only got this issue with the vuetify module enabled

No I'm not using Vuetify. Or keep-alive-props.

ping

mark

same here
any updates ?
my problem exist with keep-alive and when disable it the fetch run one time but i need keep-alive :-/

I do have the same problems now with the async fetch() method on 2.12.2. Everything inside the fetch method is called twice, basically like the fetch method is being called two times in a row, directly after each other.

I'm not using keep-alive in my pages at all and there's only one instance of nested routes, but the effects are also showing for the non-nested route pages.

My structure is like:

pages/
    - catalogue/
        - _slug.vue
        - index.vue
    - catalogue.vue
    - faq.vue
    - upcoming.vue

It happens on every page that has the async fetch() method inside of it, so for all of my pages.

Example code:

export default {
  name: 'Faq',
  async fetch () {
    console.log('fetch')
  }
}

Result from console:
image

Even with that basic version without anything else inside the component, it's being called twice.
This makes working with nuxt.js and vuex stores impossible using the fetch method as it will cause reloading of the store and flickering of the whole page when having multiple properties that are being loaded from the store (and reset before loading).

@tomhatzer the fact that you have fetch method called twice in 2.12.2 is expected behavior. If you upgraded to this version you basically opt in into a new fetch logic. You can read more about it in this articles:
https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12
https://nuxtjs.org/blog/build-dev-to-clone-with-nuxt-new-fetch

No solution was successful. I wrote this code, ignore it by taking advantage of the fact that it goes through middleware.

// middleware.js
export default async function({ req, redirect }) {
    if (req && req.url.match('undefined')) 
        redirect('/')
}

I had a dash - in one of the store property & that caused fetch getting called twice. Very weird
removing it solved it.

@nupamore @tomhatzer do you also have a dash in any store property?

I solved it by removing code outside such a block:

<div v-if="$fetchState.pending">
</div>
<div v-else>
</div>

I had a notification above the $fetchState.pending which called a function on my component which caused my fetch to be called twice.

I'm not sure this is same as this issue, but following is what I debug:

  • version: 2.14.0
  • mode: universal
  • command: nuxt-ts build && nuxt-ts start

This happens on server process (Node.js).

// .nuxt/dist/server/server.js
var server = __webpack_exports__["default"] = (async ssrContext => { ... });
  1. It works when I access to the URL that includes dynamic route like test/_testId for the first time since starting local server.

    • the above code is called once

  2. It does not work when I access to the URL as same as above second time.

    • the above code is called twice

    • the context of the first time is expected, it works correctly

    • the context of the second time seems to be broken (in my case, missing _testId because it is 'undefined')

_Tried to detect what causes this behavior, but I could not reach the caller of this function correctly._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaredreich picture jaredreich  路  3Comments

mikekidder picture mikekidder  路  3Comments

bimohxh picture bimohxh  路  3Comments

danieloprado picture danieloprado  路  3Comments

shyamchandranmec picture shyamchandranmec  路  3Comments