Razor页面中React组件引入子组件报错及模块渲染问题求助
问题描述
在Razor页面中渲染React类组件时,单独运行正常,但在App组件中导入Child子组件时出现以下错误:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
补充疑问:发现无法对模块脚本使用React.createElement,该如何实现相同功能?
相关代码
App.jsx
import { Child } from './Components/Child'; class App extends React.Component{ componentDidMount() { } render() { console.log(this.props) const list = this.props.Property1; return ( <div> <ul> {list.map(item => ( <li key={item.name}>{item.name}</li> ))} </ul> <Child></Child> </div> ); } }
Child.jsx
export class Child extends React.Component { componentDidMount() { } render() { return ( <div> Sono il figlio del component padre : {this.props.data} </div> ); } }
Index.cshtml
@using Newtonsoft.Json; @using SportData.Web.Models; @using System.Web.Optimization; @model SportContainer <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="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script> <script src="@Url.Content("~/js/app.jsx")" type="module" ></script> <script src="@Url.Content("~/js/Components/Child.jsx")" type="module"></script> <script> var modelObject = @Html.Raw(Json.Serialize(Model.sportList)); ReactDOM.render( React.createElement(App, { Property1: modelObject }), document.getElementById("App") ); </script>
问题原因及解决步骤
1. 核心问题:模块作用域隔离
你使用type="module"加载脚本,而ES模块的变量默认处于私有作用域,不会暴露到全局环境。因此后面的普通脚本无法访问App类,导致React.createElement拿到无效对象,触发报错。
2. 方案一:模块内部完成渲染(推荐)
直接在App模块中处理数据传递和渲染逻辑,避免跨作用域访问:
- 修改App.jsx,添加导出和渲染代码:
import { Child } from './Components/Child'; class App extends React.Component{ // 原代码保持不变 } // 从全局获取模型数据,执行渲染 const modelObject = window.modelObject; ReactDOM.render( React.createElement(App, { Property1: modelObject }), document.getElementById("App") ); export default App;
- 调整Index.cshtml脚本加载顺序:
<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> // 先将模型数据挂载到全局 window.modelObject = @Html.Raw(Json.Serialize(Model.sportList)); </script> <!-- 仅加载App模块,Child会被自动导入 --> <script src="@Url.Content("~/js/app.jsx")" type="module"></script>
3. 方案二:显式暴露App到全局
如果需要在外部普通脚本中调用React.createElement,可以在App.jsx末尾将组件暴露到全局:
// App.jsx最后添加 window.App = App;
这样外部脚本就能正常获取App类,原有渲染代码无需修改。
4. 关于模块化中使用React.createElement的说明
模块内完全可以正常使用React.createElement,只需确保:
- 子组件的导入/导出匹配(你的Child组件用了命名导出
export class Child和命名导入import { Child },这部分是正确的) - 根组件(App)在执行渲染时处于可访问的作用域内
内容的提问来源于stack exchange,提问作者Matteo Pagliarello

