React18+TS调用createRoot报错TypeError: m.createRoot is not a function
问题根因
这个报错和Leaflet无关,核心原因是项目运行时实际加载的react-dom版本低于18.0.0,createRoot是React 18才在react-dom中新增的API,低版本不存在该方法,你调试时看到引入的react-dom实例m上没有createRoot就是最直接的证据。
排查&修复步骤
- 校验实际安装的依赖版本
执行对应包管理工具的命令,查看项目中react、react-dom的实际安装版本:
正常要求两个包的版本均>=18.0.0,如果出现react-dom版本低于18,或者存在依赖嵌套引入了17.x版本的react-dom,就会触发该报错。# npm 用户 npm ls react react-dom # yarn 用户 yarn list react react-dom # pnpm 用户 pnpm ls react react-dom - 对齐全项目react-dom版本
如果是未升级react-dom,直接执行安装命令升级到18大版本即可:
如果是第三方依赖偷偷引入了低版本react-dom,通过包管理的强制版本配置统一全项目的react-dom版本:# npm 用户 npm install react@^18 react-dom@^18 # yarn 用户 yarn add react@^18 react-dom@^18 # pnpm 用户 pnpm add react@^18 react-dom@^18
npm 8.3+ 版本在package.json中添加如下配置:
yarn 在{ "overrides": { "react-dom": "^18.2.0" } }package.json中添加如下配置:
配置完成后重新执行依赖安装命令即可。{ "resolutions": { "react-dom": "^18.2.0" } } - 检查构建配置
如果确认所有依赖版本都符合要求仍报错,检查构建工具(webpack/vite/rollup等)的路径别名配置,是否错误将react-dom指向了本地留存的旧版本文件,修正别名指向正确的依赖路径即可。
代码优化参考
版本问题修复后,原有控件逻辑可以补充root卸载逻辑,避免内存泄漏,同时修正useEffect依赖避免重复创建控件:
import { MutableRefObject, ReactElement, useEffect } from 'react' import L, { Map } from 'leaflet' import { createRoot } from 'react-dom/client' interface MapControlElementProps { mapRef: MutableRefObject<Map | null> button: ReactElement position: L.ControlPosition } export default function TestElement(props: MapControlElementProps) { useEffect(() => { const { mapRef, button, position } = props if (!mapRef.current) return let root: ReturnType<typeof createRoot> | null = null const MapHelp = L.Control.extend({ onAdd: () => { const controlElement = L.DomUtil.create( 'div', 'leaflet-control leaflet-bar' ) root = createRoot(controlElement) root.render(button) return controlElement }, onRemove: () => { root?.unmount() } }) const control = new MapHelp({ position }) control.addTo(mapRef.current) return () => { control.remove() } }, [mapRef, button, position]) return null }
内容的提问来源于stack exchange,提问作者LLauk
相关产品推荐
相关产品推荐

