1
votes

I am using nested routes from nuxt.js: https://nuxtjs.org/guide/routing#nested-routes with a child component: https://nuxtjs.org/api/components-nuxt-child/

To make it easer to understand: I have an events page and a nested postView component. Left you can see a calendar view which stays even if the route changes. To the right I have the postdetails, which are replaced (nuxt child component):

enter image description here

With Nuxt this folder/file setup will setup my router correctly.

This works so far, but now I want to handle the case if somebody enters a non-existent postSlug in the url. So far, it would just not be displayed, but I want to have a proper 404 code. Do I have to set this manually? (I am currently making an axios call from the calendarview to see if the post.json exists. If so, I load it into the vuex store)

  …
  // if it is not in store get it via axios
  else {

    const ax = axios.create({
      baseURL: `${window.location.origin}/events`
    })
    ax.get(`event.${this.$route.params.postSlug}.json`)
    .then((response) => {
      const newActivePost = response.data && response.data.items ? response.data.items.find(p => p.slug === this.$route.params.postSlug) : false
      if (newActivePost) {
        this.activePost = newActivePost
        this.$store.dispatch('data/saveCompletePosts', this.activePost)
      }
    })
    .catch((error) => {
      console.log(error.response.data)
      console.log(error.response.status)
      console.log(error.response.headers)
    })
  }

But with this I would never get an error. Even if the json file does not exist. I always get a 200 status code.

I am not sure why this is the case, but maybe the response just contains the page without the post itself. Actually the same if I call the url with the missing post. If I have a look at the response string:

<body data-n-head="">
  <div data-server-rendered="true" id="__nuxt">
    <div class="nuxt-progress" style="width:0%;height:2px;background-color:#000000;opacity:0;"></div>
    <div id="__layout">
      <div class="Layout">
        <!---->
        <div class="SkipNavigationLink"><a href="#main" class="SkipNavigationLink__link">Springe direkt zum Hauptinhalt</a></div>
        <div class="no-ssr-placeholder"></div>
        <main id="main" class="Layout__content">
          <!---->
        </main>
        <div class="Footer">
          <div class="Footer__logo-wrapper">
            <div class="Logo"><a href="/" aria-label="Home" class="Logo__link is-active"><img src="/_nuxt/img/logo-dark.0b2ed1f.svg" alt="Logo Image" class="Logo__image"></a></div>
          </div>

You can see that there is the layout and the footer but no content. My guess would be that if I could return a proper 404 status code in the nested route/child component I would also get a 404 in my axios response.

One – maybe hacky idea – would be to manually set the status code:

    ax.get(`event.${this.$route.params.postSlug}.json`)
    .then((response) => {

      const newActivePost = response.data && response.data.items ? response.data.items.find(p => p.slug === this.$route.params.postSlug) : false
      if (newActivePost) {
        this.activePost = newActivePost
        this.$store.dispatch('data/saveCompletePosts', this.activePost)
      } else {
        // SET STATUS CODE MANUALLY?
        response.request.status = 404
      }
    })

And then handle the thing differently. But I don't know if that is a good idea...

Some help about nuxt routing/404 handling is much appreciated.

cheers

-- - - - - - - Edit I just found this https://nuxtjs.org/api/pages-validate I think this would actually call a 404 but I would not know how to validate, because there is no pattern in the postSlug. I really would have to check with all the json files of the posts...

-- - - - - - Edit 2: I can't even do that: TypeError: Cannot assign to read only property 'status' of object '#<XMLHttpRequest>' ????‍♂️

2
Did you ever get this working? I'm struggling with a similar issue of Nuxt not displaying the custom error page for non-existant routes (it shows default serever error page instead).AlxTheRed

2 Answers

0
votes

I think you are looking for error function from context

  async asynData({ params, store, error }) {
    try {
      await axioscall here
    } catch (e) {
      error({ statusCode: 404, message: 'Page not found' })
    }
  },
0
votes

Not sure if it is related, I had redirect to error page working in top level pages directory (pages/_.vue), something like this:

  async asyncData(context) {
    ...
    try {
      const response = await context.$axios(options);

      return {
        isPostLoaded: true,
        loadedPost: response.data.data.postBy
      }
    } catch (error) {
      context.error({ statusCode: 404, message: 'Page not found' });
    }
}

but it didn't work in nested directory in pages (pages/posts/_slug/index.vue) adding this seem to have helped, I checked if response data was available (might not be the best way but seem to work)

if (response.data.data.postBy === null) {
  throw new Error();
}

...

async asyncData(context) {
...
    try {
      const response = await context.$axios(options);
    
      if (response.data.data.postBy === null) {
        throw new Error();
      }
    
      return {
        isPostLoaded: true,
        loadedPost: response.data.data.postBy
      }
    } catch (error) {
      context.error({ statusCode: 404, message: 'Page not found' });
    }
}