未搭建React环境,HTML中直接使用React应用无法加载求助
React直接在HTML中加载失败的排查与修复
核心问题分析
你的代码存在三个关键问题导致React应用无法加载:
React与ReactDOM引入顺序错误
ReactDOM依赖React核心库,必须先引入React再引入ReactDOM,否则会出现React is not defined的错误。脚本执行时机过早
script.js在#root元素之前加载执行,此时document.getElementById("root")返回null,React无法找到挂载节点。React 18 API适配问题
你使用的是React 18,但仍在调用已标记为Legacy的ReactDOM.render方法,虽然兼容,但使用新API能确保稳定性。
修复步骤
1. 调整依赖引入顺序与脚本位置
修改index.html,将React放在ReactDOM之前引入,并把script.js的引用移到#root元素之后:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Markdown Previewer</title> </head> <body> <script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.18/marked.min.js"></script> <!-- 先引入React核心库 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" crossorigin></script> <!-- 再引入ReactDOM --> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" crossorigin></script> <div id="root"></div> <!-- 脚本移到#root之后,确保节点已存在 --> <script src="script.js"></script> </body> </html>
2. 适配React 18的渲染API
修改script.js中的渲染代码,使用React 18的createRoot方法替代ReactDOM.render:
// 替换原有的ReactDOM.render行 const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
3. 移除无效的Prism引用(可选)
你的marked配置中引用了Prism但未引入该库,会导致控制台报错,可直接删除这段无效代码:
marked.setOptions({ breaks: true, highlight: function (code) { return code; // 直接返回原代码,避免报错 } });
修复后的完整代码
script.js
const useState = React.useState; marked.setOptions({ breaks: true, highlight: function (code) { return code; } }); const renderer = new marked.Renderer(); const firstInput = "# H1\n" + "## H2\n" + "### H3\n" + "Here's a [link](https://www.freecodecamp.org)\n\n" + "Heres some code, `<div></div>`, between 2 backticks.\n" + "```\n" + "// this is multi-line code:\n" + "function anotherExample(firstLine, lastLine) {\n" + "if (firstLine == '```' && lastLine == '```') {\n" + " return multiLineCode;\n" + " }\n" + "}\n" + "```\n" + "> Block Quotes!\n" + "- And of course there are lists.\n" + " - Some are bulleted.\n" + " - With different indentation levels.\n" + " - That look like this.\n" + "1. And there are numbered lists too.\n" + "1. Use just 1s if you want!\n" + "1. And last but not least, let's not forget embedded images:\n\n" + "**Here's a bold text** \n" + " \n"; const App = () => { const [markdown, setMarkdown] = useState(firstInput); const handleOnChange = (event) => { setMarkdown(event.target.value); }; return ( <div id="text-center"> <h1 id="header">Markdown Previewer</h1> <div id="wrapper"> <div className="editor-wrap"> <div className="toolbar"> Editor</div> <textarea cols="50" rows="50" id="editor" value={markdown} onChange={handleOnChange} placeholder="" /> </div> <div className="preview-wrap"> <div className="toolbar"> Preview</div> <div id="preview" dangerouslySetInnerHTML={{ __html: marked(markdown, { renderer: renderer }) }} ></div> </div> </div> </div> ); }; // 使用React 18的createRoot渲染应用 const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Markdown Previewer</title> </head> <body> <script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.18/marked.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" crossorigin></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" crossorigin></script> <div id="root"></div> <script src="script.js"></script> </body> </html>
内容的提问来源于stack exchange,提问作者reactjs
相关产品推荐
相关产品推荐

