During the next build process, there seems to be an issue with getStaticPaths and getStatic

I am encountering a problem with my Next.js Application that utilizes a [slug] for Static Site Generation. Everything works perfectly fine on my localhost, but when I try to deploy it, I encounter the following error:

“Unhandled error during request: TypeError: Cannot read property ‘title’ of undefined”.

Additionally, when running the next build command on my localhost, I get this error:

Error occurred prerendering page "/jobs/[slug]". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read property 'title' of undefined

Below is the code snippet for reference:

export default function Listing({ job }) {

    const router = useRouter()

    if (!router.isFallback && !job?.slug) {
        return <ErrorPage statusCode={404} />
    }

    return (
        <div >
            <div >
                <div >
                <div >
                <div >
                <div>
                    <h1>
                    <span>Job Center</span>
                    <span >{job.title}</span>
                    <p>We are looking for interested candidates for the following position. </p>
                    </h1>
                    <div>
                            <div >
                                <span>Position: </span><span>{job.title}</span> //and multiple fields like this
                            </div>
                    </div>
                    </div>
                </div>
            </div>
        </div>
    )
    
}
 
export async function getStaticProps({ params, preview = false }) {
    const data = await getJobAndMoreJobs(params.slug, preview)
    return {
        props: {
            preview,
            job: data.job
        },
    }
}

export async function getStaticPaths() {
    const jobs = await getAllJobsWithSlug()
    return {
        paths: jobs.map(({ slug }) => ({
            params: { slug },
        })),
        fallback: true,
    }
}

In addition, there is an API file that fetches data from a GraphQL Schema and Query. The following code snippet shows how the API file functions:

async function fetchAPI(query, { variables, preview } = {}) {

    const res = await fetch(process.env.JOBS_PROJECT_API, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${
              preview
                ? process.env.JOBS_DEV_AUTH_TOKEN
                : process.env.JOBS_PROD_AUTH_TOKEN
            }`,
        },
        body: JSON.stringify({
            query,
            variables,
        }),
    })
    
    const json = await res.json()
  
    if (json.errors) {
        console.log(process.env.NEXT_EXAMPLE_CMS_GCMS_PROJECT_ID)
        console.error(json.errors)
        throw new Error('Failed to fetch API')
    }
  
    return json.data
    
}
  
export async function getPreviewPostBySlug(slug) {

    const data = await fetchAPI(
        `
        query PostBySlug($slug: String!, $stage: Stage!) {
            post(where: {slug: $slug}, stage: $stage) {
              slug
            }
        }`,
        {
            preview: true,
            variables: {
                stage: 'DRAFT',
                slug,
            },
        }
    )
    
    return data.job
    
}
  
export async function getJobAndMoreJobs(slug, preview) {

    const data = await fetchAPI(
        `
        query JobBySlug($slug: String!, $stage: Stage!) {
            job(stage: $stage, where: {slug: $slug}) {
                title
                section
                slug
                vacancies
                rank
                classification
                placeOfWork
                basicSalary
                serviceAllowance
                allowances {
                    name
                    percent
                    requirement
                }
                responsibilities
                requirement
                documents
                expirationDate
                expectedInterviewDate
                gazetteLink
                a2Form {
                    url
                }
            }
            moreJobs: jobs(orderBy: publishedAt_DESC, first: 2, where: {slug_not_in: [$slug]}) {
                title
                slug
                title
                section
                slug
                vacancies
                rank
                classification
                placeOfWork
                basicSalary
                serviceAllowance
                expirationDate
                expectedInterviewDate
                }
            }      
        `,
        {
            preview,
            variables: {
                stage: preview ? 'DRAFT' : 'PUBLISHED',
                slug,
            },
        }
    )
    
    return data
    
}

If anyone can provide assistance or insights into resolving this issue, it would be greatly appreciated! Thank you!

Answer №1

Encountered the same issue recently and found a solution in the Next.js documentation regarding getStaticPaths with fallback: true:

If fallback is set to true, the behavior of getStaticProps changes:

  • The paths that were not generated during build time will not lead to a 404 page. Instead, Next.js will serve a "fallback" version of the page on the initial request to such a path (refer to "Fallback pages" below for more details). Note: this "fallback" version will not be displayed for crawlers like Google and will instead render the path in blocking mode.

...

In the "fallback" version of a page: The page's props will be empty.

This implies that Next.js will render a fallback version of the page at build time as if you had returned props: {} from getStaticProps. The absence of a job prop being passed is causing the error you are experiencing when trying to add job.title to your JSX.

If you wish to maintain fallback: true, there are two ways to address this:

1. Handle empty page props gracefully

Ensure that the page can still render successfully even when provided an empty props object. You could use default or fallback values in this case:

export default function Listing({ job = { title: "Fallback Title" } }) {
    // ...
    return (
        <div>
            <span>{job?.title}</span>
            <span>{job?.title || "Fallback Title"}</span>
        </div>
    );
}

2. Utilize router.isFallback

If a page is being rendered as a fallback, Next.js' router will have an isFallback property set to true. You can choose to stop rendering entirely by checking for this:

export default function Listing({ job }) {

    const router = useRouter()

    if (router.isFallback) return null;

    // ...rest of component
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transferring data between AngularJS and non-AngularJS environments

Within my AngularJS application, the $scope.mydata variable holds some important data within a controller. I am currently working on a regular JSP page without any AngularJS functionality, but I need to access the data stored in the scope variable (mydat ...

Conceal a form depending on the referer_url parameter

I am looking to customize my 404 page by displaying a small form only when the visitor comes from a website, not from an email link or directly entering the URL. The purpose of this form is to address broken links that led the visitor to the error page. If ...

Parse the JSON file in the local directory and extract specific keys for each object, storing them in an array

Seeking to retrieve data from a local JSON file that contains nodeIDs with longitude, latitude, and adjacent nodeIDs as values. For example: [{"33583379": {"lat": 40.7046387, "lon": -74.0167729, "adj": ["33583379", "1659428533"]}, "33583380": {"lat": 40.7 ...

React - triggering a router link action before the link is assigned a value

In this scenario, the issue arises because the URL changes before the link receives a value. The state is being received directly through the component but by the time it happens, the component has already been clicked. This results in the value being as ...

Issue adding dictionary value to an array in JavaScript

Let's analyze the code snippet below: var array = []; var obj = [{id: "xxxxx", name: "Friend name"}, {id: "xxxxx", name: "Friend name"}] for (x in obj){ array.push(x.name) } After running this code, the array ends up with the correct length but ...

Numerous obj elements simultaneously loaded within a single viewport

My goal is to incorporate multiple obj models into separate scenes, following the concept from webgl_multiple_elements.html. I have successfully loaded a single obj file and now want to add it to each individual scene. Although the obj file loads without ...

The TypeScript Promise error codes TS2304 and TS2529 are causing confusion among

I came across the code below: function asyncTask(): Promise<string> { return new Promise<string>(resolve => resolve); } This code resulted in the following error: TS2304: cannot find name 'Promise' To address this issue, ...

Numerous requests for GetStaticProps are causing my application to freeze during the build process and result in a server error

I need to compile a long list of products and I want to fetch data using node in order to build the page statically for faster loading on the homepage. The issue arises when I try to make over 80 requests with GetStaticProps method. The code below works ...

Is it advisable to consider yarn.lock as a binary file when using git?

Could there be a rationale for this decision? I'm thinking that the potential git diff could occur in package.json. My approach is to consider the yarn.lock file as binary. ...

Leveraging the power of NextJS and Strapi: Efficiently fetching multiple API pages with a single getStaticPaths

Both NextJs and Strapi offer guidance on fetching data from a single collection type within Strapi. The process involves the following code snippet: const pages = await (await fetch(getStrapiURL("/pages"))).json(); const paths = pages.map((page) => { ...

Is your React application struggling to display large images when bundled with Webpack?

I am facing an issue while trying to display an image from my image folder in a React project using Webpack. I have observed that smaller photos with physically smaller dimensions and file sizes load properly, but larger photos do not render on the screen, ...

How can you capture the VIRTUAL keyCode from a form input?

// Binding the keydown event to all input fields of type text within a form. $("form input[type=text]").keydown(function (e) { // Reference to keyCodes... var key = e.which || e.keyCode; // Only allowing numbers, backspace, and tab if((key >= 48 && ke ...

Ways to output HTML from a function

I'm struggling to get my HTML function to work properly, even though it seems like a simple task. For some reason, the content isn't displaying when I return it, but things work fine when using console.log. Could someone please assist me with th ...

Using DefaultSeo does not override NextSeo in every component

I am looking to dynamically change the Head tag using next-seo. While browser validation will show NEXTSeo for individual pages, Twitter, Firebase's card validation tool, and others will default to next-seo-config.js. Does anyone have a solution? S ...

Preventing typing by detecting keypresses in a text input

I'm trying to set up a text input field so that it triggers a function when the Enter key is pressed. I currently have an if condition to check for the Enter key press, but this prevents users from typing in the input box. What should I include in the ...

Instead of displaying the location attribute in an alert, populate it into a text area

I have a function that can retrieve my current location using longitude and latitude coordinates. However, I am looking to automatically fill a text area (Populate Here) with the results instead of displaying an alert. <!DOCTYPE html> <html> ...

Update the color of navigation items to reflect their active status

Here is the snippet of HTML code: <header> <nav> <a href="#" id="menu-icon"></a> <ul> <li><a href="#"">Home</a></li> <li><a href="#">About</a></li> & ...

React cannot be utilized directly within HTML code

I am looking to incorporate React directly into my HTML without the need for setting up a dedicated React environment. While I can see the test suite in the browser, my React app fails to load. Below is the content of my script.js file: I have commented ...

Trouble uninstalling Rails Destroy functionality after integrating Bootstrap using Webpacker

I am working on a Rails project and encountering a few challenges. Progress so far Initially, I incorporated Bootstrap into the project using CDN links in the application.html.erb file in layouts. This allowed me to achieve the desired formatting, but the ...

What is the best way to prevent a selected <option> in one <select> from being selected in another <select>, while also making sure this applies to both new and existing &

Currently, I am working with a code snippet that disables select options based on similar fields. The code can be found here. $(document).on('shown.oc.popup', function() { let options = $('.variantPlacementOptions:first select').c ...