Nuxt.js: [Bug] Pages mount twice

Created on 6 Oct 2017  路  15Comments  路  Source: nuxt/nuxt.js

In the "spa mode" with a "custom layout" pages will be mounted twice!

screen shot 2017-10-06 at 7 09 18 pm

In a fresh clone of nuxt.js, I just added this line in nuxt.config.js to use spa mode:
mode: 'spa',

then I created a custom layout ('layouts/custom.vue') with the exact contents of the default layout ('layouts/default.vue'), and I used the custom layout in "pages/index.vue"

This bug only exists in SPA mode with a custom layout. But in SSR mode or with the default layout it works fine.

This bug report is available on Nuxt.js community (#c1606)
bug-confirmed

Most helpful comment

Hey @davidpmccormick

It's actually due to the fact that we wait for fetch to finish before making the transition, and if the second one is faster, it's due to browser cache.

One solution is to check in your fetch method if you are from client-side, if so, you can avoid to wait for the promise and instead show a loading text :)

All 15 comments

I also noticed this. First thought it's a vuejs issue, but seems nuxt related and also happens in spa mode. It calls mounted twice

so is there a way to prevent this issue?

waiting for this issue solved, i just use page components as proxy to vue component in components folder.

Can you verify that this only happens with pages and not _all components_?

yups i use rc11, this is only happens to pages compnents, i'v tried,

I have that issue too.
Additionally, when using page transitions, duplicated page component shows for few milliseconds and disappears.

Dirty _fix_ for now is to hide this component with SCSS (remember, it won't fix js code calling twice):
```SCSS

__nuxt {

& > *:nth-child(3) {
  display: none;
}

}

Fixed in next release.

I'm unsure if this is related (I'm not using spa mode) but similar to @mkurczewski's point above, I'm seeing leave transitions occur _after_ the new page content has rendered.

I'm using fetch() to update a Vuex store.

The behaviour is only intermittent 鈥撀爏ee the first click on 'the trust' in the gif below; the heading displays before the leave transition (although this doesn't happen on the second click)

transition-timing

I'm on "nuxt": "^1.1.1"

Hey @davidpmccormick

It's actually due to the fact that we wait for fetch to finish before making the transition, and if the second one is faster, it's due to browser cache.

One solution is to check in your fetch method if you are from client-side, if so, you can avoid to wait for the promise and instead show a loading text :)

@Atinux Thanks for the info 鈥撀爓ould you mind giving a beginner a little bit more context?

Currently I have

async fetch({ store, params }) {
  await store.dispatch('getPageById', params.pageSlug);
}

I think you're suggesting something like

async fetch({ store, params, isClient }) {
  if (isClient) {
    // I'm not sure what to do here
  } else {
    await store.dispatch('getPageById', params.pageSlug);
  }
}

Test site running here: http://btmat-nuxt.herokuapp.com/
Repo here: https://github.com/davidpmccormick/btmat-nuxt

Update

I solved my issue by using asyncData and returning the necessary data from the store after I'd dispatched some actions. For example:

async asyncData({ store }) {
  await store.dispatch('getArticleStubs');

  return {
    articleStubs: store.state.articleStubs
  };
}

But I'm not any clearer on why this way does what I want and fetch doesn't.

I'm having the same problem as @davidpmccormick only for me it happens on every click/page change, the new page content transitions out and then in.

This is when using fetch to populate the store. If I switch to asyncData as mentioned above the problem goes away, but this feels kind of hacky and I also don't understand why the behaviour is different from fetch.

So before I move ahead to refactor to asyncData I would really like to know, is there some explanation/solution to this?

I was able to test for req.headers.referer as this only loads when coming from the client...I guess...
I'm doing this in nuxtServerInit btw:

async nuxtServerInit ({ dispatch }, { req }) {

  if (process.server && req.headers.referer) { // <= only fires once =)

    const cookies = getCookie.s(req),
          token = cookies.token

    if (token) {
      this.$axios.setToken(token, 'Bearer')
      const api = "http://server:1337/member/verify"
      let { success, message, data: user } = await this.$axios.$get(api)
      if (!success) throw message
      // @todo ~ Error handling )
      await dispatch('user/setUser', user)
    }
  }
}

UPDATE:
Ignoring headers.referer was a bad idea. Instead, I realized that it's triggering the css.map file as a nuxt server call. This seems to work fine for my purposes:

if (process.server && req && req.url && !req.url.match(/\.map$/)) {
  // code...
}

nextTick https://vuejs.org/v2/api/#mounted solved the issue for me. I had an ajax call in mounted and was getting fired twice (no-ssr component), not SPA mode though

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  路  3Comments

bimohxh picture bimohxh  路  3Comments

jaredreich picture jaredreich  路  3Comments

gary149 picture gary149  路  3Comments

lazycrazy picture lazycrazy  路  3Comments