deprecated icon indicating copy to clipboard operation
deprecated copied to clipboard

getInitialData not called when leaving error route to the same component

Open IlyaSemenov opened this issue 7 years ago • 1 comments

If client-side navigation (<router-link>) is used to switch from the error page to an another page but both the error page URL and new page URL resolve into the same route component, getInitialData is not called due to false positive duplicate check in router.beforeResolve at app/client-entry.js

Steps to reproduce

Create page component:

<template>
<div>
  <router-link to="/a">a</router-link>
  <router-link to="/b">b</router-link>
  <router-link to="/c">c</router-link>
  current page: {{ page }}
</div>
</template>

<script>
export default {
  getInitialData (context) {
    if (context.route.path === '/c') {
      context.router.app.setError({ code: 404, message: 'not found', errorPath: context.route.path })
      return
    }
    return {
      page: context.route.path
    }
  }
}
</script>

error component:

<template>
<div>
  <router-link to="/a">a</router-link>
  <router-link to="/b">b</router-link>
  <router-link to="/c">c</router-link>
  error: {{ error }}
</div>
</template>

<script>
export default {
  props: [ 'error' ]
}
</script>

and entry file:

import Router from 'vue-router'

import test from '@/pages/test'
import error from '@/pages/error'

export default function () {
  return {
    router: new Router({
      mode: 'history',
      routes: [
        { path: '/:path(.*)', component: test }
      ]
    }),
    error
  }
}

Then open http://localhost:4000/a

Expected result

Switching between /a, /b and /c works fine in any order and regardless of which page was generated with SSR at first.

Actual result

Switching between /a and /b will work fine. Switching from /a or /b to /c will display error as expected. However, switching from /c to /a will crash:

[Vue warn]: Property or method "page" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

---> <Test> at src/pages/test.vue
       <ReamRoot>
         <Root>

and the page info will be empty:

a b c current page:

IlyaSemenov avatar Aug 24 '18 03:08 IlyaSemenov

If you're curious the rationale for this architecture is that the actual content is pulled from an API based CMS in getInitialData, so it may generate 404 for arbitrary URLs. However, the error page reuses the base template and includes the menu with <router-link>'s. So currently once a user lands on a 404 page, he may not proceed further.

IlyaSemenov avatar Aug 24 '18 03:08 IlyaSemenov