未触发Nextjs getStaticProps

时间:2020-11-02 16:48:15

标签: javascript reactjs next.js

下面的我的[slug] .js文件具有两个nextjs帮助器函数。 getStaticPaths和getStaticProps被导出。就我而言,它创建路径posts/[slug]。添加了一个名为hello.json的帖子文件。现在,当我导航到localhost:3000/posts/hello时,它会说:

TypeError: Cannot read property 'fileRelativePath' of undefined。对于第10行。

看到jsonFile未定义后,这才有意义。事实上,从未调用整个getStaticProps,也从未记录过其中的登录。为什么会这样?

谢谢。

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,
    };
};

1 个答案:

答案 0 :(得分:0)

深入研究后,我发现了这个问题,在这里发帖希望对以后遇到同样问题的读者有所帮助。

罪魁祸首是这个:

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

在动态导入中使用变量无效,只能使用字符串或模板文字。我使用了一个变量,因为存在eslint解析错误,该错误只能通过降级到eslint的较早版本来解决。这导致eslint在该文件中不适合我使用,但是好吧,至少调用了该函数。

这与观察到在调用getStaticProps之前调用组件代码的观察相结合,使得jsonFile变量未定义,并且整个组件在到达getStaticProps之前就出错了。您可以看到以121212开头的日志早于1212。终端日志:

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

这对我来说很直观,因为我认为它会首先获取道具并将其立即传递给组件,但可悲的是,需要定义默认道具来解决此问题。

新代码:

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,
    };
}