我如何 运行 与 iFrame 中的钩子反应

How can I run React with hooks in an iFrame

我正在编写一个 React 应用程序,我想在其中通过 iFrame 动态呈现 React 组件。我在网页上有一个代码编辑器,允许用户编写他们的 React 代码,我希望它将代码呈现到页面上嵌入的 iFrame 中。

此 html(存储在 htmlString 中)通过其 srcdoc 直接传递到 iFrame。


<!DOCTYPE HTML>
    <html lang="en">
     <head> 
      <meta charset="utf-8">
      <title>My New Snippet</title>
    </head>
    
    <body>
      <div id="app"> </div>
    
      <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
      <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
      <script type="application/javascript" src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
      <script defer type="text/babel">
        console.log(React);
        const { useState } = React
    
        const App = (props) => { 
          const [text, setText] = useState('hello');
    
          return (
            <div>
              <h1>{text}</h1>
              <input type="text" value={text} onChange={(e) => setText(e.target.value)} />
            </div>
          );
        }
    
        ReactDOM.render(
          App(),
        document.getElementById('app')
        );
    
      </script>
    </body> 
  </html>

这是 iFrame 在我的组件的渲染部分中的样子:


<iframe
  srcDoc={htmlString}
  width="100%"
  height="100%"
  title="output"
  sandbox="allow-scripts"
/>

当运行代码时,我得到以下错误:


Uncaught TypeError: Cannot read properties of null (reading 'useState')
    at useState (react.development.js:1610:23)
    at App (<anonymous>:12:19)
    at <anonymous>:31:17
    at run (babel.js:61531:11)
    at check (babel.js:61597:10)
    at loadScripts (babel.js:61638:4)
    at runScripts (babel.js:61668:4)
    at transformScriptTags (babel.js:336:40)
    at babel.js:327:13

对我来说,这看起来像是 React 没有在上下文中定义,但是通过 console.logs,我能够确认它确实存在于正确的范围内。

像这样尝试,ReactDOM.render 在 React 18 版本中已被弃用,您包含在 React 18 脚本中。

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>My New Snippet</title>
</head>

<body>
<div id="app"> </div>

<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script type="application/javascript" src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
<script defer type="text/babel">
    console.log(React);
    const { useState } = React
    const { createRoot } = ReactDOM ;

    const App = (props) => {
        const [text, setText] = useState('hello');

        return (
            <div>
                <h1>{text}</h1>
                <input type="text" value={text} onChange={(e) => setText(e.target.value)} />
            </div>
        );
    }
    const container = document.getElementById('app');
    const root = createRoot(container);
    root.render(<App />);
</script>
</body>
</html>

在此处阅读更多内容 DOC