如何从不可序列化的数据(函数)创建页面
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
.
传递
gatsby-node.js
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,
});
}
});
};
gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `test`,
path: `${__dirname}/src/test/`,
},
},
],
}
src/templates/test.js
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 组件。
我有这个 JavaScript 数据文件(src/test/test.js
):
module.exports = {
"title": "...",
"Number": "number1",
"Number2": ({ number1 }) => number1 / 2,
}
我想将此文件逐字(保留功能)传递给一个页面,以便该页面可以使用该数据来构建自己。我已经有了页面模板和其他所有东西,我只需要找到一种方法将其传递到页面中。
我尝试的第一种方法是 require
将此文件放入 gatsby-node.js
,然后将其作为 pageContext
.
gatsby-node.js
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,
});
}
});
};
gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `test`,
path: `${__dirname}/src/test/`,
},
},
],
}
src/templates/test.js
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 组件。