Javascript 如何从JSON文件在Gatsby中创建页面?
我正在尝试使用JSON文件在Gatsby中动态创建一个页面。在该文件中,我定义了应该在页面中呈现的组件 我遵循盖茨比的文档,但是,它没有我想要的。因此,我试图通过读取JSON文件并遍历其中的组件并使用React.createElement()创建页面。最后,我得到了一个react组件数组,我将该数组传递给createPage方法上下文对象中的一个children prop,并将其传递给模板页面组件 这是解决这个问题的正确方法吗?这在盖茨比是否可行 我想说我尝试了动态导入,效果很好,这是很有用的,但我正在尝试找到一种方法,不必将所有组件转储到一个文件夹中 我有这个项目的Github回购协议。 以下是代码的主要部分: gatsby-node.jsJavascript 如何从JSON文件在Gatsby中创建页面?,javascript,reactjs,gatsby,react-context,Javascript,Reactjs,Gatsby,React Context,我正在尝试使用JSON文件在Gatsby中动态创建一个页面。在该文件中,我定义了应该在页面中呈现的组件 我遵循盖茨比的文档,但是,它没有我想要的。因此,我试图通过读取JSON文件并遍历其中的组件并使用React.createElement()创建页面。最后,我得到了一个react组件数组,我将该数组传递给createPage方法上下文对象中的一个children prop,并将其传递给模板页面组件 这是解决这个问题的正确方法吗?这在盖茨比是否可行 我想说我尝试了动态导入,效果很好,这是很有用的,
exports.createPages = ({actions})=>{
const {createPage} = actions
const resutl = componentsRenderer(data.page.layout.columns)
createPage({
path: data.page.name,
component: path.resolve('./src/template/page.js'),
context:{
children: resutl
}
})
}
const componentsRenderer = components => {
return components.map(component => {
let children = []
if (component.children){
children = componentsRenderer(component.children)
}
const element = require(`${__dirname}/${component.path}`)
return React.createElement(element, Object.assign({},{key: component.key},{...component.props}),children)
});
}
data/sample-page-no-props.json
{
"page":{
"name": "about",
"layout":{
"columns": [
{
"key":"column_1",
"name": "Column",
"path": "/src/components/layouts/column.jsx",
"children":[
{
"name": "FirstComponent",
"path": "/src/components/custom/first-component.jsx",
"key": "first_component_1"
}
]
},
{
"key": "column_2",
"name": "Column",
"path": "/src/components/layouts/column.jsx",
"children":[
{
"key": "second_component_1",
"name": "SecondComponent",
"path": "/src/components/custom/second-component.jsx",
"children":[
{
"key": "leaf_component_1",
"name": "LeafComponent",
"path":"/src/components/custom/leaf-component.jsx"
}
]
},
{
"key": "third_component_1",
"name": "ThirdComponent",
"path": "/src/components/custom/third-component.jsx",
"children":[
{
"key": "leaf_component_1",
"name": "LeafComponent",
"path":"/src/components/custom/leaf-component.jsx"
}
]
}
]
}
]
}
}
}
data/sample-page-with-style-prop.json(FirstComponent有props对象)
模板/page.js
import React from 'react'
import Layout from '../components/layouts/Layout'
const Page = (props)=>{
console.log(`page_context: ${props.pageContext.children}`)
return (
<>
<h1>this is the about page</h1>
<Layout>
{props.pageContext.children}
</Layout>
</>
)
}
export default Page
从“React”导入React
从“../components/layouts/Layout”导入布局
常量页面=(道具)=>{
log(`page\u context:${props.pageContext.children}`)
返回(
这是关于页面
{props.pageContext.children}
)
}
导出默认页面
components/custom/first-component.jsx
// import React from "react";
const React = require("react");
module.exports = (props)=>{
return(
<h3 style={props.style}>
Hi this is the first component
</h3>
)
}
// export default FirstComponent
//从“React”导入React;
常量反应=要求(“反应”);
module.exports=(道具)=>{
返回(
嗨,这是第一个组件
)
}
//导出默认组件
我在使用sample-page-with-style-prop.json文件时遇到的错误如下:
UNHANDLED REJECTION Cannot assign to read only property 'style' of object '#<Object>'
TypeError: Cannot assign to read only property 'style' of object '#<Object>'
无法将未处理的拒绝分配给对象“#”的只读属性“style”
TypeError:无法指定对象“#”的只读属性“style”
如果更改为sample-page-no-props.json文件,则会出现以下错误:
UNHANDLED REJECTION Cannot assign to read only property 'children' of object '#<Object>'
TypeError: Cannot assign to read only property 'children' of object '#<Object>'
无法将未处理的拒绝分配给对象“#”的只读属性“children”
TypeError:无法分配给对象“#”的只读属性“children”
而不是将组件作为上下文传递给页面模板。正确的方法是传递数据并在页面中呈现组件
gatsby node.js
exports.createPages = ({actions})=>{
const {createPage} = actions
const resutl = componentsRenderer(data.page.layout.columns)
createPage({
path: data.page.name,
component: path.resolve('./src/template/page.js'),
context:{
children: resutl
}
})
}
import React from 'react'
import Layout from '../components/layouts/Layout'
const componentsRenderer = components => {
return components.map(component => {
let children = []
if (component.children){
children = componentsRenderer(component.children)
}
const element = require(`${HOME_DIR}/${component.path}`)
return React.createElement(element, Object.assign({},{key: component.key},{...component.props}),children)
});
}
const Page = (props)=>{
const data = props.pageContext.children
return (
<>
<h1>this is the about page</h1>
<Layout>
{componentsRenderer(data)}
</Layout>
</>
)
}
export default Page
模板/page.js
exports.createPages = ({actions})=>{
const {createPage} = actions
const resutl = componentsRenderer(data.page.layout.columns)
createPage({
path: data.page.name,
component: path.resolve('./src/template/page.js'),
context:{
children: resutl
}
})
}
import React from 'react'
import Layout from '../components/layouts/Layout'
const componentsRenderer = components => {
return components.map(component => {
let children = []
if (component.children){
children = componentsRenderer(component.children)
}
const element = require(`${HOME_DIR}/${component.path}`)
return React.createElement(element, Object.assign({},{key: component.key},{...component.props}),children)
});
}
const Page = (props)=>{
const data = props.pageContext.children
return (
<>
<h1>this is the about page</h1>
<Layout>
{componentsRenderer(data)}
</Layout>
</>
)
}
export default Page
从“React”导入React
从“../components/layouts/Layout”导入布局
const componentsrender=组件=>{
返回components.map(component=>{
让孩子们=[]
if(子组件){
children=componentsrender(component.children)
}
const element=require(`${HOME\u DIR}/${component.path}`)
返回React.createElement(元素,对象.assign({},{key:component.key},{…component.props}),子元素)
});
}
常量页面=(道具)=>{
const data=props.pageContext.children
返回(
这是关于页面
{componentsrender(数据)}
)
}
导出默认页面
PS:确保页面组件中的
HOME\u DIR
路径正确。非常感谢您的回复,我正在尝试您的建议。不幸的是,它没有起作用。我得到错误:元素类型无效:需要字符串(对于内置组件)或类/函数(对于复合组件),但得到:对象。这可能是因为我没有将require更改为es6导入(实际上使用可加载组件),但这将使它成为一个动态导入,我已经这样做了,而且效果很好。我正在寻找替代方案,因为我的团队选择不进行动态导入。似乎您应该将组件作为默认值导出,并作为默认值导入,如const element=require(`${HOME\u DIR}/${component.path}`)。默认值