JSX 字符串转 React Element 的几种方案

在 React 项目中,有时我们需要处理 JSX 字符串并将其转换为真正的 React 元素,比如从 CMS 获取模板或构建可视化编辑器时。本文介绍三种实用方案及其优缺点。

react-jsx-parser 是一个简单安全的方案,

import JsxParser from 'react-jsx-parser';

<JsxParser jsx="<div>Hello</div>" components={{ MyComponent }} />

优势:

  • 配置简单,安装即用
  • 不执行函数定义(有效防 XSS 攻击)
  • 支持白名单组件,可控性好

缺点:

  • 不支持函数声明 (function xxx(){})
  • 逻辑表达式支持有限
  • 动态性较弱,复杂场景力不从心

适合场景:
渲染小型 JSX 模板,且对安全性要求高的场景,比如从用户输入或第三方 CMS 获取内容时。

react-live 支持完整的函数、组件和 hooks,尤其适合需要实时编辑预览的场景~

基本用法:

import { LiveProvider, LivePreview } from 'react-live';

<LiveProvider code="() => <div>Hello World</div>" noInline>
  <LivePreview />
</LiveProvider>

优势:

  • 支持完整函数、组件和 hooks 语法
  • 自带动态实时编辑功能(做编辑器超方便)
  • 内置 Error 捕获,不怕崩溃

缺点:

  • 执行过程有安全风险(需额外注意)
  • 通常限于编辑器类场景
  • 打包体积会比简单方案大一些

适合场景:
需要动态运行完整 React 代码的场景,如技术博客的代码演示、React 学习平台等。

这是最灵活的方案,通过手动 transform 编译再用 new Function 执行,可以实现最大程度的自定义。

基本实现:

import { transform } from '@babel/standalone';

function jsxToElement(jsxString) {
  const compiledCode = transform(jsxString, { presets: ['react'] }).code;
  const Component = new Function('React', `return (${compiledCode})`)(React);
  return React.createElement(Component);
}

// 使用示例
const element = jsxToElement(`() => <div>Hello Dynamic JSX</div>`);

优势:

  • 最灵活,几乎没有功能限制!
  • 支持各种高级特性(async/await、函数组件、hooks、状态管理等)
  • 真正实现"输入 JSX 字符串 → 输出 React 元素"的完整转换

缺点:

  • 需要自己处理安全风险(防止恶意代码执行)
  • Babel 体积较大(如果整体引入而非按需加载)

适合场景:
需要高度自定义运行环境的场景,如高级 CMS 系统、动态表单渲染器、自建 Playground 等。

处理字符串转 JSX 最大的风险是执行恶意代码。以下是一些实用的安全措施,建议根据项目需求选择性使用~

  1. 黑名单关键词检查
    直接扫描代码中的危险词如 windowdocumenteval 等,快速过滤明显的攻击代码。

  2. 严格模式限制
    使用 new Function('React', '"use strict"; return (...)') 强制开启严格模式,防止 this 指向全局对象。

  3. 异常捕获
    用 try-catch 包裹所有执行过程,遇到错误立即显示友好提示,避免页面崩溃。

    try {
      return jsxToElement(code);
    } catch (err) {
      return <div className="error">渲染出错: {err.message}</div>;
    }
    
  4. 返回类型校验
    检查返回值是否为合法的 React 元素,防止运行时异常。

  • AST 深度扫描:利用 Babel parser 进行语法树分析,能更精确地识别危险代码模式。
  • iframe 沙盒隔离:将动态代码放在隔离环境中执行,即使有问题也不会影响主应用。

选择建议:

  • 小型项目,对安全性要求高:选择 react-jsx-parser
  • 需要实时编辑预览功能:选择 react-live
  • 需要最大灵活性和控制力:选择 babel-standalone + new Function