简体   繁体   中英

Nextjs getStaticProps not fired

My [slug].js file, below, has two nextjs helper functions. The getStaticPaths and getStaticProps are exported. In my case, it creates the path posts/[slug] . There is one post file added called hello.json . Now when I navigate to localhost:3000/posts/hello it errors saying:

TypeError: Cannot read property 'fileRelativePath' of undefined . For line 10.

This makes sense after seeing that jsonFile is undefined. As a matter of fact, the whole getStaticProps is never called, the log in there is never logged. Why is this happening?

Thanks in advance.

import React from 'react';
import glob from 'glob';
import { usePlugin } from 'tinacms';
import { useJsonForm } from 'next-tinacms-json';

const Page = ({ jsonFile }) => {
    console.log(121212, jsonFile);

    // Create the tina form
    const [post, form] = useJsonForm(jsonFile);

    // Register it with the CMS
    usePlugin(form);

    return (
        <h1>
            {post.title}
        </h1>
    );
};

export default Page;

/**
 * By exporting the async function called getStaticProps from a page, Next.js
 * pre-renders this page at build time using the props returned by
 * getStaticProps.
 * The getStaticPaths function defines a list of paths that have
 * to be rendered to HTML at build time.
 */

export async function getStaticProps({ ...ctx }) {
    console.log(1212, ctx);
    const { slug } = ctx.params;
    const dynamicPath = `../../posts/${slug}.json`; // for eslint parsing error: "Cannot read property 'range' of null Occurred while linting"
    const content = await import(dynamicPath);

    console.log(121212, content);

    return {
        props: {
            jsonFile: {
                fileRelativePath: `/posts/${slug}.json`,
                data: content.default,
            },
        },
    };
}

export async function getStaticPaths() {
    //get all .json files in the posts dir
    const posts = glob.sync('posts/**/*.json');

    const paths = posts.map(file => ({
        params: {
            slug: `${file.replace('.json', '')}`,
        },
    }));

    return {
        paths,
        fallback: true,
    };
};

After some more digging around I found the issue, posting here to hopefully help future readers with the same issue.

The culprit was this:

const dynamicPath = `../../posts/${slug}.json`; // for eslint parsing error: "Cannot read property 'range' of null Occurred while linting"
const content = await import(dynamicPath);

Using a variable in a dynamic import does not work, only strings or template literals. I used a variable because of a eslint parsing error that can only be resolved by downgrading to an earlier version of eslint. This causes eslint to not work for me in this file, but okay, at least the function is called.

This combined with the observation that the component code is called before the getStaticProps is called made the jsonFile variable undefined and the whole component erroring before it'll ever reach the getStaticProps . You can see that the log starting with 121212 is coming in earlier than 1212 . Terminal logs:

121212 {
  fileRelativePath: 'posts/hello.json',
  data: { title: 'Not the actual data' }
}
1212 hello

This is counter intuitive to me as I figured it would first get the props and pass them to the component immediately, but sadly, defining default props is needed to work around this.

New code:

import React from 'react';
import glob from 'glob';
import { usePlugin } from 'tinacms';
import { useJsonForm } from 'next-tinacms-json';

const Page = ({ jsonFile }) => {
    console.log(121212, jsonFile);

    // Get content and form for Tina
    const [content, form] = useJsonForm(jsonFile);

    // Register it with the CMS
    usePlugin(form);

    return (
        <h1>
            {content.title}
        </h1>
    );
};

Page.defaultProps = {
    jsonFile: {
        fileRelativePath: 'posts/hello.json',
        data: {
            title: 'Not the actual data',
        },
    },
};

export default Page;

/**
 * By exporting the async function called getStaticProps from a page, Next.js
 * pre-renders this page at build time using the props returned by
 * getStaticProps.
 */
export async function getStaticProps({ params: { slug } }) {
    console.log(1212, slug);

    // This line caused the issue
    // const dynamicPath = (`../../posts/${slug}.json`; // for eslint parsing error: "Cannot read property 'range' of null Occurred while linting"
    const content = await import(`../../posts/${slug}.json`);

    return {
        props: {
            jsonFile: {
                fileRelativePath: `posts/${slug}.json`,
                data: content.default,
            },
        },
    };
}

/**
 * The getStaticPaths function defines a list of paths that have
 * to be rendered to HTML at build time.
 */
export async function getStaticPaths() {
    //get all .json files in the posts dir
    const posts = glob.sync('posts/**/*.json');

    return {
        paths: posts.map(file => ({
            params: {
                slug: `${file.replace('.json', '')}`,
            },
        })),
        fallback: true,
    };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM