【问题标题】:Contentful richText with next.js带有 next.js 的内容丰富的富文本
【发布时间】:2021-10-22 13:31:33
【问题描述】:

我正在尝试在我的博客中集成内容丰富的富文本,并且它仅适用于粗体、段落和斜体。我无法让图像和嵌入的东西出现。

首先我有这个组件:

const Content = ({ content }) => {
  return (
    <div className="content-body-contentful">
      {documentToReactComponents(content)}
    </div>
  )
}

然后,在帖子页面中,我导入该组件并像这样传递数据:

&lt;Content content={article.fields.body} /&gt;

这个问题有答案吗?

【问题讨论】:

  • 您能否发布您正在尝试渲染的content 以及用于图像和“嵌入式事物”的组件或渲染器? documentToReactComponents 尝试将 nodeType 映射到组件,或者您需要传入自定义渲染器。
  • 感谢您的回答。我试图渲染一个富文本字段,它包含一个段落和一个图像。据我所知,我不仅要传递内容,还要传递 nodeTypes,比如 documentToReactComponents(content, options, richTextDocument) ,但是我怎样才能在 Content 组件中获取 article.fields.body 呢?
  • 兄弟你的问题解决了吗?

标签: javascript reactjs next.js contentful contentful-api


【解决方案1】:

嗨@user13680445,内容中的 Richtext 字段总是返回类似这样的内容,至少作为 Graphql 响应

"richTextResponse": {
  // JSON structure of the Rich Text field
  "json": {
    # ...
  }
  // all referenced assets/entries
  "links": {
    # ...
  }
}

在链接字段中,您可以获得嵌入在 Richtext 中的所有资产和条目

这里我在 Typescript 中有一个如何添加资产的示例

    export const renderOptions = (links: Links): Options => {
      const assetMap = getAssets(links.assets.block);
      const entryMap = getEntries(links.entries.block);
    
      return {
        renderNode: {
          [BLOCKS.HEADING_1]: renderHeading,
          [BLOCKS.PARAGRAPH]: renderParagraph,
          [BLOCKS.EMBEDDED_ENTRY]: renderEntry(entryMap),
          [BLOCKS.EMBEDDED_ASSET]: renderAsset(assetMap),
        },
      };
    };
    
const renderAsset =
  (assetMap: Map<string, ContentfulImage>): NodeRenderer =>
  (node) => {
    const asset = assetMap.get(node.data.target.sys.id);
    if (!asset) {
      return <></>;
    }
    switch (asset.contentType) {
      case "video/mp4":
        return (
          <VideoAsset
            url={asset.url}
            width={asset.width}
            height={asset.height}
          />
        );
      case "image/png":
      case "image/jpeg":
        return (
          <ImageAsset
            url={asset.url}
            width={600}
            height={450}
            description={asset.description}
            quality={75}
          />
        );
      default:
        return "Nothing to see here...";
    }
  };

然后你可以像这样调用那个函数:

{documentToReactComponents(json, renderOptions(links))}

这是一种基本的方法,但 Contentful 目前没有更好的方法。

我们得到了与 nodeType 中的 sys.id 和资产链接中的 sys.id 匹配的资产数据 例如:

富文本对象

{
  "nodeType": "embedded-asset-block",
  "content": [],
  "data": {
    "target": {
      "sys": {
        "id": "2DdSHQJA8zoumehPzqWZrs",
        "type": "Link",
        "linkType": "Asset"
      }
    }
  }
}

链接对象

"links": {
  "assets": {
    "block": [
      {
        "sys": {
          "id": "2DdSHQJA8zoumehPzqWZrs"
        },
        "fileName": "GOPR0511.JPG",
        "url": "https://images.ctfassets.net/",
        "title": "GOPR0511"
      }
    ]
  }
}

我们基于 sys.id 连接两者,在这种情况下,是 2DdSHQJA8zoumehPzqWZrs

【讨论】:

    【解决方案2】:

    以下是通过 Contentful 将图像与 Next.js 一起使用的示例。您可以类似地实现其余项目。

    import Image from 'next/image'
    
    const renderProps = {
        renderNode: {
            [BLOCKS.EMBEDDED_ASSET]: node => {
                let { description, file } = node.data.target.fields
    
                return (
                    <picture>
                        <Image src={file.url} alt={description} />
                    </picture>
                )
            },
        },
    }
    const Content = ({ content }) => {
        return <div className="content-body-contentful">{documentToReactComponents(content, renderProps)}</div>
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-26
      • 2021-11-14
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 2017-10-23
      • 2023-03-05
      相关资源
      最近更新 更多