Nuxt page not fetching data if routed from broken page

17 views Asked by At

I have a site that shows job listings, so it has a /pages/jobs/index.vue and a /pages/jobs/_slug.vue to show a main jobs page and a child page for each job.

The child and parent page use the Contentful delivery API to fetch data about the jobs.

If I navigate to a child page that doesn't exist e.g. /jobs/blahblah then I've added an error message and cta that links back to the main jobs page. However, when I do this and click the cta to go back to /jobs the jobs page fails to fetch the Contentful data and shows an empty page.

If I navigate to a job child page that does exist, then navigate to the main jobs page, everything is fine.

I saw other people suggest using a watch function, that watches for url changes and refetches the data. So I tried this (see /pages/jobs/index.vue), using the 2 ways I could find online but it didn't help:

watch: {
          'this.$route.query': '$fetch'
      },
    watchQuery: true,

/pages/jobs/_slug.vue:

 <template>
  <div>
    <Subpage
      v-if="!$fetchState.pending"
      :navLinks="navLinks"
      :heroData="heroData"
      :childPage="true"
    />
    <div v-if="$fetchState.error">
      <p>Sorry, this job is no longer available</p>
      <CallToAction url="/jobs" label="Check out our other jobs" />
    </div>
    <div v-else>
    <div class="job-details-container">
      <h2>Job Outline</h2>
      <div 
        class="job-outline"
        v-html="this.jobOutline"
      ></div>
    </div>
    </div>
  </div>
</template>

<script>
import Vue from "vue";
import { fetchEntriesByContentType } from "../../../services/contentful-service";
import Subpage from "../../../components/header/Subpage.vue";
import CallToAction from "../../../components/CallToAction.vue";
import { documentToHtmlString } from "@contentful/rich-text-html-renderer";
export default {
  name: "job-details",
  components: { Subpage, CallToAction },
  data() {
    return {
      slug: '',
      pageData: {},
      seoMetaData: {},
      navLinks: [],
    };
  },
  async fetch() {
    try {
      const path = this.$route.path;
      const slug = path.split("/")[path.split("/").length - 1];

      const [job] = await fetchEntriesByContentType({
        contentType: "jobsCard",
        slug,
      });
      const [navbar] = await fetchEntriesByContentType({
        contentType: "navbar"
      });

      if (!job || !navbar) {

        throw `Error-fetching jobs child page data`;
      } else {
        this.pageData = job?.fields;
        this.seoMetaData = job?.fields?.jobDetail
        this.navLinks = navbar;
        this.slug = slug;
      }
    } catch (e) {
      if (process.env.ROLLBAR_ENABLED === true) {
        Vue.rollbar.error(e);
      }
      throw new Error(e);
    }
  },

  computed: {
    heroData() {
      return {
        pageTitle: this.pageData?.jobTitle,
        heroImageUrl: this.pageData?.jobDetail.image.url
      };
    },
    jobOutline() {
      return documentToHtmlString(this.pageData?.jobDetail?.fields?.jobOutline);
    },
  },
};
</script>

/pages/jobs/index.vue:

<template>
  <div>
    <Subpage
      v-if="!$fetchState.pending"
      :navLinks="navLinks"
      :heroData="heroData"
    />
    <div>
     
      <ul>
        <JobCard
          v-for="card in jobCards"
          :key="getCardTitle(card)"
          :jobData="{ ...card.fields, itemId: card.sys.id }"
        />
      </ul>
    </div>
  </div>
</template>

<script>
import Vue from "vue";
import Subpage from "../../../components/header/Subpage.vue";
import JobCard from "../../../components/jobs/JobCard.vue";

import { fetchEntriesByContentType } from "../../../services/contentful-service";

export default {
  name: "jobs-page",
  components: { Subpage, JobCard },
  data() {
    return {
      headerData: {},
      seoMetaData: {},
      jobCards: [],
    };
  },
  watch: {
      'this.$route.query': '$fetch'
  },
watchQuery: true,
  async fetch() {
    try {
      const data = await fetchEntriesByContentType({
        contentType: "pageSection",
        title: "Jobs",
      });

      if (!data || data.length < 1) {
        throw `Error- fetching jobs page data`;
      } else {
        this.headerData = data[0].fields?.header;
        this.seoMetaData = data[0].fields?.seoMetadata?.fields || {};
        this.jobCards = data[0].fields?.bodySection?.fields?.jobCard;
        }
      } catch (error) {
        if (process.env.ROLLBAR_ENABLED === true) {
          Vue.rollbar.error(error);
        }
        throw new Error(error);
      }
  },
  methods: {
    getCardTitle(card) {
      return card?.fields?.title;
    },
  },

  computed: {
    navLinks() {
      return this.headerData?.fields?.navBar;
    },
    heroData() {
      return {
        subPageIntro: this.headerData?.fields?.heroSection?.fields.introText,
      }
    },
  },
};
</script>
0

There are 0 answers