如何在Next.js中将Draft.js区块渲染为React组件
解决Draft.js转HTML时替换为Next/Image组件的方案
核心思路
draftjs-to-html、draft-js-export-html这类库的作用是生成HTML字符串,直接返回React组件会被转为[Object object]——因为库只接受字符串类型的渲染结果。正确的做法是分两步处理:
- 先转成带识别标记的标准HTML字符串
- 在React渲染阶段解析HTML,将目标img标签替换为Next/Image组件
步骤1:生成带标记的HTML字符串
修改draftjs-to-html的自定义渲染器,给图片标签添加自定义data属性,方便后续识别:
import draftToHtml from 'draftjs-to-html'; const customRenderers = { image: (block) => { const { src, alt = '' } = block.data; // 给img标签添加自定义标记属性 return `<img data-next-image src="${src}" alt="${alt}" />`; } }; // 从数据库取出的EditorState JSON先转为EditorState,再生成HTML const htmlContent = draftToHtml(editorState.getCurrentContent(), customRenderers);
步骤2:解析HTML并替换为Next/Image组件
使用react-html-parser库解析HTML字符串,在解析过程中替换目标img标签:
import React from 'react'; import Image from 'next/image'; import parse from 'react-html-parser'; const renderOptimizedContent = (html) => { return parse(html, { transform: (node) => { // 匹配我们标记的img标签 if (node.type === 'tag' && node.name === 'img' && node.attribs['data-next-image']) { const { src, alt = '' } = node.attribs; return ( <Image src={src} alt={alt} fill // 若使用fill模式,需确保父容器为相对定位 className="blog-image" sizes="100vw" priority={false} /> ); } // 其他标签保持原样渲染 return node; } }); }; // 组件中使用示例 const BlogPost = ({ editorStateJson }) => { // 此处省略将JSON转为EditorState的逻辑,可使用convertFromRaw const htmlContent = draftToHtml(editorState.getCurrentContent(), customRenderers); return ( <div className="blog-post-content"> {renderOptimizedContent(htmlContent)} </div> ); }; export default BlogPost;
注意事项
- 确保在
next.config.js中配置图片域名白名单,避免Next/Image报错:/** @type {import('next').NextConfig} */ const nextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'your-image-host.com', // 替换为你的图片域名 port: '', pathname: '/**', }, ], }, }; module.exports = nextConfig; - Next/Image的尺寸配置:根据布局需求选择
width/height固定尺寸,或fill配合父容器相对定位 - 若不想额外引入
react-html-parser,也可以自己编写正则表达式替换img标签为React组件的JSX字符串,再结合组件渲染,但这种方式复杂度更高,不如使用成熟的解析库
内容的提问来源于stack exchange,提问作者Guilherme Luis
相关产品推荐
相关产品推荐

