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

React中如何渲染外部API返回的HTML与JavaScript内容?

在React中渲染外部API返回的HTML和JavaScript内容

方法1:使用dangerouslySetInnerHTML(仅渲染HTML,不执行JS)

如果响应中的JavaScript无需执行,仅需渲染HTML结构,可通过React的dangerouslySetInnerHTML属性直接插入HTML字符串:

import { useState, useEffect } from 'react';

function ExternalContent() {
  const [htmlContent, setHtmlContent] = useState('');

  useEffect(() => {
    const url = getExternalEndpoint();
    fetch(url)
      .then(response => response.text())
      .then(data => setHtmlContent(data))
      .catch(err => console.error('请求失败:', err));
  }, []);

  return (
    <div dangerouslySetInnerHTML={{ __html: htmlContent }} />
  );
}

export default ExternalContent;

注意:该方法不会执行HTML中的JavaScript代码,React会过滤脚本标签以规避XSS风险。

方法2:手动操作DOM执行脚本(支持JS运行)

若需要执行响应中的JavaScript,需手动操作DOM插入内容并提取脚本执行:

import { useState, useEffect, useRef } from 'react';

function ExternalContent() {
  const contentRef = useRef(null);

  useEffect(() => {
    const url = getExternalEndpoint();
    fetch(url)
      .then(response => response.text())
      .then(data => {
        if (!contentRef.current) return;
        
        // 清空容器
        contentRef.current.innerHTML = '';
        // 创建临时容器存放响应内容
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = data;
        
        // 将HTML元素移入目标容器
        while (tempDiv.firstChild) {
          contentRef.current.appendChild(tempDiv.firstChild);
        }
        
        // 提取并执行脚本
        const scripts = contentRef.current.querySelectorAll('script');
        scripts.forEach(script => {
          const newScript = document.createElement('script');
          // 复制原脚本属性
          Array.from(script.attributes).forEach(attr => {
            newScript.setAttribute(attr.name, attr.value);
          });
          // 处理内联脚本内容
          if (script.textContent) newScript.textContent = script.textContent;
          // 处理外部脚本地址
          if (script.src) newScript.src = script.src;
          // 替换原脚本避免重复执行
          script.parentNode.replaceChild(newScript, script);
        });
      })
      .catch(err => console.error('请求失败:', err));
  }, []);

  return <div ref={contentRef} />;
}

export default ExternalContent;

方法3:使用iframe加载(安全隔离执行环境)

如果外部内容包含复杂JS逻辑,或需要隔离执行环境,iframe是更安全的选择:

import { useState, useEffect } from 'react';

function ExternalContent() {
  const [iframeSrc, setIframeSrc] = useState('');

  useEffect(() => {
    const url = getExternalEndpoint();
    fetch(url)
      .then(response => response.text())
      .then(data => {
        // 将HTML内容转为Blob生成可访问URL
        const blob = new Blob([data], { type: 'text/html' });
        const url = URL.createObjectURL(blob);
        setIframeSrc(url);
        
        // 组件卸载时释放URL资源
        return () => URL.revokeObjectURL(url);
      })
      .catch(err => console.error('请求失败:', err));
  }, []);

  return <iframe src={iframeSrc} width="100%" height="600" frameBorder="0" />;
}

export default ExternalContent;

关键注意事项

  • 安全风险:直接渲染外部HTML和JS存在XSS隐患,需确保外部API(如你提到的OpenID Connect服务器)是完全可信的。
  • 跨域问题:若fetch请求触发CORS错误,需确认外部服务器是否允许你的域名跨域访问,或通过后端代理转发请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 08:45:25