如何从 JSON 文件在 Gatsby 中创建页面?
How to create a page in Gatsby from JSON file?
我正在尝试使用 JSON 文件在 Gatsby 中动态创建页面。在那个文件中,我定义了应该在页面中呈现的组件。
我按照 Gatsby 的文档,但是,它没有我想要的。因此,我尝试通过读取 JSON 文件并遍历其中的组件并使用 React.createElement() 创建它们来创建页面。最后,我得到了一个反应组件数组,我将其传递给模板页面组件的 createPage 方法的上下文对象中的子道具。
这是解决这个想法的正确方法吗?它在 Gatsby 中是否可行?
我认为说我尝试过动态导入并且它工作正常是有用的,但我正在尝试找到一种不必将所有组件转储到一个文件夹中的方法。
我有这个项目的 Github 回购协议。
https://github.com/ahmedalbeiruti/Gatsby-dynamic-pages
下面是代码的主要部分:
盖茨比-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
}
})
}
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":{
"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",
"props":{
"style":{
"color":"red"
}
}
}
]
},
{
"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"
}
]
}
]
}
]
}
}
}
template/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
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
我在使用 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>'
如果我更改为 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>'
而不是将组件作为上下文传递给页面模板。正确的方法是传递数据并在 Page
中呈现组件
盖茨比-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
}
})
}
template/page.js
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
PS: 确保页面组件中的HOME_DIR
路径是正确的。
我正在尝试使用 JSON 文件在 Gatsby 中动态创建页面。在那个文件中,我定义了应该在页面中呈现的组件。
我按照 Gatsby 的文档,但是,它没有我想要的。因此,我尝试通过读取 JSON 文件并遍历其中的组件并使用 React.createElement() 创建它们来创建页面。最后,我得到了一个反应组件数组,我将其传递给模板页面组件的 createPage 方法的上下文对象中的子道具。
这是解决这个想法的正确方法吗?它在 Gatsby 中是否可行?
我认为说我尝试过动态导入并且它工作正常是有用的,但我正在尝试找到一种不必将所有组件转储到一个文件夹中的方法。
我有这个项目的 Github 回购协议。 https://github.com/ahmedalbeiruti/Gatsby-dynamic-pages
下面是代码的主要部分:
盖茨比-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
}
})
}
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":{
"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",
"props":{
"style":{
"color":"red"
}
}
}
]
},
{
"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"
}
]
}
]
}
]
}
}
}
template/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
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
我在使用 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>'
如果我更改为 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>'
而不是将组件作为上下文传递给页面模板。正确的方法是传递数据并在 Page
中呈现组件盖茨比-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
}
})
}
template/page.js
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
PS: 确保页面组件中的HOME_DIR
路径是正确的。