无法使用 Gatsby.js 从 Contentful headless cms 正确呈现富文本字段
Can't properly render rich text field from Contentful headless cms using Gatsby.js
因此,我正在为本地企业建立一个网站,他们可以在其中使用内容丰富的 cms(类似于以前工作的博客)添加以前的工作(这是一种翻新类型的业务)。
我遇到的问题是我需要在哪里显示在 contentful 中定义为富文本字段的每个作业的内容。
我将向您展示我的项目组件(这是一个通过 gatsby create pages api 创建页面的模板),它是:
import React from 'react';
import { graphql } from 'gatsby';
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import { BLOCKS } from "@contentful/rich-text-types"
import Layout from '../components/layout';
const Project = ({data}) => {
const RichContent = JSON.parse(data.contentfulProject.projectContent.raw);
const options = {
renderNode: {
[BLOCKS.HEADING_1]: (node, children) => <h1>{children}</h1>,
// [BLOCKS.EMBEDDED_ASSET]: <img src={`https:${data.contentfulProject.projectContent.references.fluid.src}`}/>,
},
renderMark: {},
}
console.log(data)
return (
<Layout>
{documentToReactComponents(RichContent, options)}
</Layout>
)
}
export default Project;
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
title
projectContent {
raw
references {
fluid {
src
}
}
}
}
}
`
所以实际上我成功地呈现了文本字段,但是当我取消注释 [BLOCKS.EMBEDED_ASSET] 时由于缺少数据而导致分页中断。图片未显示。
我的猜测是在查询内容完整的数据时我无法访问 json 字段,我只得到原始字段。
请帮忙:D
设法解决了问题,这里是正常显示图像的工作组件的代码:
import React from 'react'
import { graphql } from 'gatsby';
import { renderRichText } from "gatsby-source-contentful/rich-text"
import { BLOCKS } from "@contentful/rich-text-types"
import Layout from '../components/layout'
function ProjectTemplate({ data }) {
const {projectContent} = data.contentfulProject
console.log(projectContent)
const options = {
renderMark: {},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => <p>{children}</p>,
[BLOCKS.EMBEDDED_ASSET]: node => {
return (
<img src={`https:${node.data.target.fixed.src}`}/>
)
},
},
}
return (
<div>
<Layout>
{renderRichText(projectContent, options)}
</Layout>
</div>
)
}
export default ProjectTemplate
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
contentful_id
title
slug
projectContent {
raw
references {
... on ContentfulAsset {
contentful_id
__typename
fixed(width: 1600) {
width
height
src
srcSet
}
}
}
}
}
}
`
使用如下结构:
import { BLOCKS, MARKS } from "@contentful/rich-text-types"
import { renderRichText } from "gatsby-source-contentful/rich-text"
const Bold = ({ children }) => <span className="bold">{children}</span>
const Text = ({ children }) => <p className="align-center">{children}</p>
const options = {
renderMark: {
[MARKS.BOLD]: text => <Bold>{text}</Bold>,
},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => <Text>{children}</Text>,
[BLOCKS.EMBEDDED_ASSET]: node => {
return (
<>
<h2>Embedded Asset</h2>
<pre>
<code>{JSON.stringify(node, null, 2)}</code>
</pre>
</>
)
},
},
}
renderRichText(node.bodyRichText, options)
每种类型的字段都有自己的 renderNode
,这让您可以非常灵活地决定如何使用自己的组件来呈现和设置数据样式。
使用 BLOCKS.EMBEDDED_ASSET
你的代码没有返回任何东西,使用上面的代码片段,你可以自定义输出,如果需要绕过它返回一个空对象。
在您的查询中,您不必指定引用,只需原始就足够了。
将您的查询修改为如下所示:
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
contentful_id
title
slug
projectContent {
raw
}
}
}
`
因此,我正在为本地企业建立一个网站,他们可以在其中使用内容丰富的 cms(类似于以前工作的博客)添加以前的工作(这是一种翻新类型的业务)。
我遇到的问题是我需要在哪里显示在 contentful 中定义为富文本字段的每个作业的内容。
我将向您展示我的项目组件(这是一个通过 gatsby create pages api 创建页面的模板),它是:
import React from 'react';
import { graphql } from 'gatsby';
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import { BLOCKS } from "@contentful/rich-text-types"
import Layout from '../components/layout';
const Project = ({data}) => {
const RichContent = JSON.parse(data.contentfulProject.projectContent.raw);
const options = {
renderNode: {
[BLOCKS.HEADING_1]: (node, children) => <h1>{children}</h1>,
// [BLOCKS.EMBEDDED_ASSET]: <img src={`https:${data.contentfulProject.projectContent.references.fluid.src}`}/>,
},
renderMark: {},
}
console.log(data)
return (
<Layout>
{documentToReactComponents(RichContent, options)}
</Layout>
)
}
export default Project;
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
title
projectContent {
raw
references {
fluid {
src
}
}
}
}
}
`
所以实际上我成功地呈现了文本字段,但是当我取消注释 [BLOCKS.EMBEDED_ASSET] 时由于缺少数据而导致分页中断。图片未显示。
我的猜测是在查询内容完整的数据时我无法访问 json 字段,我只得到原始字段。
请帮忙:D
设法解决了问题,这里是正常显示图像的工作组件的代码:
import React from 'react'
import { graphql } from 'gatsby';
import { renderRichText } from "gatsby-source-contentful/rich-text"
import { BLOCKS } from "@contentful/rich-text-types"
import Layout from '../components/layout'
function ProjectTemplate({ data }) {
const {projectContent} = data.contentfulProject
console.log(projectContent)
const options = {
renderMark: {},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => <p>{children}</p>,
[BLOCKS.EMBEDDED_ASSET]: node => {
return (
<img src={`https:${node.data.target.fixed.src}`}/>
)
},
},
}
return (
<div>
<Layout>
{renderRichText(projectContent, options)}
</Layout>
</div>
)
}
export default ProjectTemplate
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
contentful_id
title
slug
projectContent {
raw
references {
... on ContentfulAsset {
contentful_id
__typename
fixed(width: 1600) {
width
height
src
srcSet
}
}
}
}
}
}
`
使用如下结构:
import { BLOCKS, MARKS } from "@contentful/rich-text-types"
import { renderRichText } from "gatsby-source-contentful/rich-text"
const Bold = ({ children }) => <span className="bold">{children}</span>
const Text = ({ children }) => <p className="align-center">{children}</p>
const options = {
renderMark: {
[MARKS.BOLD]: text => <Bold>{text}</Bold>,
},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => <Text>{children}</Text>,
[BLOCKS.EMBEDDED_ASSET]: node => {
return (
<>
<h2>Embedded Asset</h2>
<pre>
<code>{JSON.stringify(node, null, 2)}</code>
</pre>
</>
)
},
},
}
renderRichText(node.bodyRichText, options)
每种类型的字段都有自己的 renderNode
,这让您可以非常灵活地决定如何使用自己的组件来呈现和设置数据样式。
使用 BLOCKS.EMBEDDED_ASSET
你的代码没有返回任何东西,使用上面的代码片段,你可以自定义输出,如果需要绕过它返回一个空对象。
在您的查询中,您不必指定引用,只需原始就足够了。
将您的查询修改为如下所示:
export const query = graphql`
query($id: String!) {
contentfulProject(id: {eq: $id}) {
contentful_id
title
slug
projectContent {
raw
}
}
}
`