You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NextJS项目中调用API获取并使用含React组件的HTML内容?

实现HTML编辑器中嵌入React组件并在NextJS中渲染的方案

直接存储原生React组件代码到数据库再渲染存在严重安全风险(XSS攻击、任意代码执行),因此推荐采用自定义标签占位符的方案,既满足编辑器输入需求,又能安全渲染组件:

核心思路

  1. 在HTML编辑器中用约定的自定义标签(如<CustomButton text="提交" />)替代原生React组件代码
  2. 后端直接存储混合了HTML和自定义标签的字符串
  3. 前端从API获取内容后,先做安全净化,再将自定义标签解析为对应的React组件

具体实现步骤

1. 定义编辑器输入规范

让管理员在HTML编辑器中使用首字母大写的自定义标签(避免和原生HTML标签冲突),示例:

  • 按钮组件:<CustomButton text="点击跳转" link="/about" />
  • 轮播组件:<CustomCarousel images="[img1.jpg, img2.jpg]" />
  • 普通HTML内容可正常输入

2. 前端渲染处理(NextJS)

需要用到两个工具库:

  • dompurify:净化HTML,拦截XSS攻击
  • html-react-parser:将HTML字符串转换为React元素,并支持自定义标签替换

安装依赖

npm install dompurify html-react-parser
# 或
yarn add dompurify html-react-parser

实现渲染组件

import React from 'react';
import DOMPurify from 'dompurify';
import parse from 'html-react-parser';

// 定义允许渲染的自定义组件白名单
const CustomComponents = {
  CustomButton: ({ text, link }) => (
    <a href={link} className="btn btn-primary">
      {text}
    </a>
  ),
  CustomCarousel: ({ images }) => {
    const imgList = JSON.parse(images);
    return (
      <div className="carousel">
        {imgList.map((img, idx) => (
          <img key={idx} src={img} alt={`slide-${idx}`} />
        ))}
      </div>
    );
  },
};

// 自定义标签转换逻辑
const transform = (node) => {
  // 只处理首字母大写的自定义标签
  if (node.type === 'tag' && node.name[0] === node.name[0].toUpperCase()) {
    const Component = CustomComponents[node.name];
    if (!Component) return; // 不在白名单的标签直接忽略

    // 转换标签属性为组件props
    const props = node.attribs || {};
    return <Component {...props} />;
  }
};

export default function HomePage({ htmlBody }) {
  // 先净化HTML内容,移除危险代码
  const cleanHtml = DOMPurify.sanitize(htmlBody);
  // 解析并替换自定义标签为React组件
  const renderedContent = parse(cleanHtml, { transform });

  return <div className="home-content">{renderedContent}</div>;
}

// 从API获取数据(SSG/SSR示例)
export async function getStaticProps() {
  const res = await fetch('你的API接口地址');
  const data = await res.json();
  return { props: { htmlBody: data.htmlBody } };
}

3. 安全加固

  • 严格限制自定义组件白名单,只保留业务必需的组件
  • 用dompurify过滤所有HTML内容,移除<script>、onclick等危险标签和属性
  • 对组件props做类型校验(如PropTypes/TypeScript),防止恶意属性注入
  • 后端额外添加内容校验,拦截不符合规范的标签

不推荐的替代方案(仅内部可信场景参考)

如果必须允许输入原生JSX代码,只能通过eval或new Function执行,但会带来极高安全风险,仅适合完全可信的内部管理员使用:

// 极不安全,禁止生产环境使用
const renderJSX = (jsxString) => {
  const Component = eval(`(() => React.createElement(${jsxString}))()`);
  return Component;
};

内容的提问来源于stack exchange,提问作者Hadroge Tempest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:27:16