【问题标题】:Add React component in HTML set by dangerouslySetInnerHTML在由 dangerouslySetInnerHTML 设置的 HTML 中添加 React 组件
【发布时间】:2026-01-24 17:20:02
【问题描述】:

我从需要通过dangerouslySetInnerHTML 注入的服务器接收到HTML。插入 HTML 后,我想获得一个 DOM 元素,其 id 为:home_content

这是因为我从遗留应用程序(服务器端呈现的 HTML)迁移到 React,遗留应用程序返回 HTML。这个 React 组件的目标是将 HTML 从遗留应用程序解析为 React 组件。在这个组件中,我想将 React 组件添加到从服务器接收到的初始 HTML 结构中。

export default function App() {
  const [data, setData] = useState({});
  const [isLoading, setIsLoading] = useState(true);
  const didMountRef = useRef(false);

  const pageName = useSetPageTitle();

  // Will be replaced by the actual API call, Add to legacy component
  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(
        `http://127.0.0.1:8000/nav?action=${pageName}`
      );
      const legacyHTML = await response.text();
      setData(legacyHTML);
      setIsLoading(false);
    };
    fetchData();

    didMountRef.current = true;
  }, [pageName]);

  useEffect(() => {
    if(didMountRef.current) {
      const domContainer = document.querySelector("#home_content");
      ReactDOM.render(<LikeButton />, domContainer);
    }
  }, [didMountRef]);

  return (
    <>
      <LegacyDependencies />
      <div>
        <div id="content"></div>
        {isLoading ? (
          <div>
            <span>loading...</span>
          </div>
        ) : (
          <div
            dangerouslySetInnerHTML={{
              __html: data,
            }}
          />
        )}
      </div>
    </>
  );
}

我收到以下错误:Error: Target container is not a DOM element.

是否可以在dangerouslySetInnerHTML 插入的 HTML 中添加 React 组件?

【问题讨论】:

  • @Mohit 这没有回答问题。
  • 您问是否可以添加 React 组件,因为我分享了链接,因为您从服务器获取的 html 应该是正确的,是的,您可以注入它。
  • 您的示例展示了如何在 React 组件中解析 HTML。问题是关于将 React 组件添加到 dangerouslySetInnerHTML 插入的 HTML
  • 仔细阅读,需要使用__html属性传递React组件/html。

标签: javascript reactjs


【解决方案1】:

你可以这样做。

const { useRef, useState, useEffect } = React;

const getData = () => Promise.resolve('<div id="content">Test</div>')

const LikeButton = () => <button>Like!</button>

const App = () => {
  const ref = useRef();
  const [data, setData] = useState('');

  useEffect(() => {
    let isUnmounted = false
    getData()
      .then(pr => {
        if(isUnmounted) {
          return
        }
        
        setData(pr);
      })
      
    return () => {
      isUnmounted = true;
    }
  }, []);

  useEffect(() => {
    const element = ref && ref.current;

    if(element) {
     const content = document.getElementById("content");
     if(content) {
      ReactDOM.render(<LikeButton />, content);
     }
    }
  }, [ref, data])

return <div ref={ref} dangerouslySetInnerHTML={{
    __html: data,
  }}></div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>

【讨论】: