ASP.NET Core MVC中React组件console.log无输出及未定义问题
开发ASP.NET Core MVC项目时,在Razor页面使用React类组件,页面能正常渲染组件并显示Property1、Property2属性,但componentDidMount、render方法及点击事件里的所有console.log语句均无输出。尝试多种方案后未解决,后续在Index.cshtml末尾添加React初始化脚本,组件显示正常,但控制台提示App组件未定义。
React组件代码
class App extends React.Component{ componentDidMount() { console.log('hi') } render() { console.log(this.props) const { Property1, Property2 } = this.props const handler = (event) => { console.log(event); } return ( <div> <button onClick={handler}> clicca </button> {console.log(this.props)} <p>Property1: {Property1}</p> <p>Property2: {Property2}</p> <div className="box">Sono un box</div> </div> ); } }
初始Index.cshtml代码
@Html.React("App",new { Property1 = "value1", Property2 = "value2" }) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
Program.cs代码
// 配置应用服务 var builder = WebApplication.CreateBuilder(args); // 添加容器服务 builder.Services.AddControllersWithViews(); builder.Services.AddMvc().AddRazorRuntimeCompilation(); builder.Services.AddReact(); builder.Services.AddHttpContextAccessor(); builder.Services.AddJsEngineSwitcher(option => option.DefaultEngineName = V8JsEngine.EngineName).AddV8(); var app = builder.Build(); // 配置HTTP请求管道 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseReact(config => { config.AddScript("~/js/App.jsx"); }); ReactSiteConfiguration.Configuration.JsonSerializerSettings.ContractResolver = new DefaultContractResolver(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
编辑后的Index.cshtml代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title> - SportData</title> <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="/css/site.css?v=_5WottCwlLwmnX08KuvZv3ryqfP5c42il12e6LRxHqg" /> <link rel="stylesheet" href="/css/card.css?v=ZXutknPLolnM8AJ6Dofwp6kVw_54LAeyyWSi8YLbEeY" /> </head> <body> <div class="container"> <main role="main" class="pb-3"> <div id="react_0HMO2J0AM8AAV"><div data-reactroot=""><button> clicca </button><p>Property1: <!-- -->value1</p><p>Property2: <!-- -->value2</p><div class="box">Sono un box</div></div></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script> <script>ReactDOM.hydrate(React.createElement(App, {"Property1":"value1","Property2":"value2"}), document.getElementById("react_0HMO2J0AM8AAV"));</script> <!-- 此行报错 --> </main> </div> <script src="/lib/jquery/dist/jquery.min.js"></script> <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <!-- Visual Studio Browser Link --> <script type="text/javascript" src="/_vs/browserLink" async="async" id="__browserLink_initializationData" data-requestId="6501a3e3c110465981ca8b97a81c1842" data-requestMappingFromServer="false" data-connectUrl="http://localhost:57481/dc7f1eca94044a1ca53edfa6de85d80f/browserLink"></script> <!-- End Browser Link --> <script src="/_framework/aspnetcore-browser-refresh.js"></script></body> </html>
问题原因及解决方法
1. 控制台日志无输出的原因
使用@Html.React时采用的是**服务器端渲染(SSR)**模式:组件的render方法在服务器端执行,生成静态HTML返回给浏览器,而客户端的生命周期方法(如componentDidMount)、事件绑定逻辑不会在服务器端运行。浏览器拿到的只是静态DOM,没有客户端React的运行环境,所以console.log不会在浏览器控制台输出。
2. 添加初始化脚本后提示App未定义的原因
手动添加ReactDOM.hydrate脚本时,客户端未加载App组件的代码:服务器端渲染仅在服务器执行组件逻辑,不会将App类的JS代码输出到客户端,导致客户端执行React.createElement(App)时找不到全局的App对象。
具体解决步骤
方案1:保留SSR并启用客户端Hydration(推荐)
确保客户端加载React、ReactDOM以及App组件的代码,React.AspNet库会自动生成Hydration脚本,无需手动编写:
@Html.React("App",new { Property1 = "value1", Property2 = "value2" }) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script> <!-- 引入App组件脚本,确保路径正确 --> <script src="~/js/App.jsx"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
注意:若
App.jsx使用JSX语法,需提前编译为浏览器可识别的JS代码,开发环境可临时用babel-standalone编译,生产环境建议预编译。
方案2:改用纯客户端渲染
如果不需要SSR,直接在客户端初始化组件:
- 移除
@Html.React调用 - 添加空DOM容器
- 用
ReactDOM.render初始化组件:
<div id="app"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script> <script src="~/js/App.jsx"></script> <script> ReactDOM.render( React.createElement(App, {"Property1":"value1","Property2":"value2"}), document.getElementById('app') ); </script>
内容的提问来源于stack exchange,提问作者Matteo Pagliarello

