如何从不可序列化的数据(函数)创建页面

How to create pages from non-seriazable data(functions)

我有这个 JavaScript 数据文件(src/test/test.js):

module.exports = {
    "title": "...",
    "Number": "number1",
    "Number2": ({ number1 }) => number1 / 2,
}

我想将此文件逐字(保留功能)传递给一个页面,以便该页面可以使用该数据来构建自己。我已经有了页面模板和其他所有东西,我只需要找到一种方法将其传递到页面中。


我尝试的第一种方法是 require 将此文件放入 gatsby-node.js,然后将其作为 pageContext.

传递
const path = require('path');

exports.createPages = ({actions, graphql}) => {
    const { createPage } = actions;

    return graphql(`
        query loadQuery {
            allFile(filter: {sourceInstanceName: {eq: "test"}}) {
                edges {
                    node {
                        relativePath
                        absolutePath
                    }
                }
            }
        }
    `).then(result => {
        if (result.errors) {
            throw result.errors;
        }

        for (const node of result.data.allFile.edges.map(e => e.node)) {
            const data = require(node.absolutePath);
            createPage({
                path: node.relativePath,
                component: path.resolve('./src/templates/test.js'),
                context: data,
            });
        }
    });
};
module.exports = {
    plugins: [
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                name: `test`,
                path: `${__dirname}/src/test/`,
            },
        },
    ],
}
import React from 'react';

const index = ({ pageContext }) => (
    <p>{pageContext.Number2()}</p>
);

export default index;

但是,当 运行 开发服务器:

时,我收到此警告
warn Error persisting state: ({ number1 }) => number1 / 2 could not be cloned.

如果我忽略它并尝试使用该函数,Gatsby 会因以下错误而崩溃:

WebpackError: TypeError: pageContext.Number2 is not a function

经过一段时间的搜索,我找到了这个:

The pageContext was always serialized so it never worked to pass a function and hence this isn't a bug. We might have not failed before though.
- Gatsby#23675

告诉我这种方法行不通。

如何将这些数据传递到页面中?我考虑过 JSON,但是,JSON 不能包含函数。

我也尝试过寻找一种直接注册 JSX 对象的方法,但是我找不到方法。

关于主题,如您所见,不能那样做,因为数据是序列化的。

How could I pass this data into a page? I've considered JSON instead, however, JSON can't contain functions.

好吧,这是部分正确的。您可以随时执行以下操作:

{"function":{"arguments":"a,b,c","body":"return a*b+c;"}}

然后:

let func = new Function(function.arguments, function.body);

在这种情况下,您正在(反)序列化一个 JSON 函数,根据 JSON 参数创建和转换一个函数。这种方法可能适用于您的场景。

关于 JSX,我想你可以尝试类似的东西:

for (const node of result.data.allFile.edges.map(e => e.node)) {
    const data = require(node.absolutePath);
    createPage({
        path: node.relativePath,
        component: path.resolve('./src/templates/test.js'),
        context:{
          someComponent: () => <h1>Hi!</h1>
        },
    }); 
}

然后:

import React from 'react';

const Index = ({ pageContext: { someComponent: SomeComponent} }) => (
    return <div><SomeComponent /></div>
);

export default index;

注:不知道是不是问题打错了,不过index应该大写为Index

在这种情况下,您将 someComponent 别名为 SomeComponent,这是一个有效的 React 组件。