React渲染时为何用React.createElement包裹函数组件而非直接调用取返回值
两种写法的本质差异
直接调用App()/Welcome({name: 'Sara'})本质是手动执行函数拿到返回的React元素对象,而用React.createElement(App)/<App />是创建一个组件描述符,告知React「此处需要渲染一个App类型的组件」,React后续的状态管理、hooks调度、重渲染等所有组件相关逻辑都依赖这个描述符。
两种写法在你给出的无状态静态组件场景下渲染结果一致,但只要涉及动态逻辑,直接调用函数的写法会立刻出现问题,具体差异如下:
- hooks 完全失效
如果你的组件内使用了useState、useEffect等React Hook,直接调用函数的写法会直接报错。Hook的运行依赖React的组件渲染上下文,只有当React主动调度执行组件函数时,才会维护对应的Hook状态链表,手动调用函数没有这个上下文,会直接抛出「Hook 只能在函数组件内部调用」的错误。
示例:
const App = () => { // 直接调用App()时该行直接报错 const [count, setCount] = React.useState(0) return React.createElement("div", {}, count) }
- 组件无法响应重渲染
即使没有用到Hook,当涉及父组件重渲染、props更新的场景,直接调用函数返回的元素会被React当成普通静态节点,不会触发对应组件的重渲染逻辑。比如父组件传递给Welcome的name属性变化时,直接调用Welcome({name: Sara})拿到的是一次性的静态元素,不会自动更新内容,只有交给React管理组件实例时,才会在props变更时重新执行组件函数拿到最新的渲染结果。 - 无法使用React组件相关的内置能力
后续你如果要给组件配置defaultProps、propTypes,或者用React.memo做渲染优化,甚至使用Suspense、Context等框架能力,都依赖React识别到节点是组件实例,直接调用函数返回的普通元素无法触发这些逻辑。
综上,直接调用组件函数只在无状态无更新的极端场景下可用,属于巧合的可用,不是规范写法,所以官方和讲师都会使用React.createElement(组件)的规范写法。
内容的提问来源于stack exchange,提问作者user16037629
相关产品推荐
相关产品推荐

