使用esm.sh引入react-three-fiber时触发Invalid Hook call错误的解决求助
问题描述
我尝试通过esm.sh运行react-three-fiber的Canvas组件,编写了如下HTML代码:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <script type="importmap"> { "imports": { "@jsxImportSource": "https://esm.sh/react@18.2.0?dev", "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?dev", "@react-three/fiber": "https://esm.sh/@react-three/fiber?dev" } } </script> <script type="module" src="https://esm.sh/run"></script> <title>Document</title> </head> <body> <div id="root"></div> <script type="text/babel" > import {createRoot} from 'react-dom/client'; import {Canvas} from '@react-three/fiber'; function App() { return ( <div> <Canvas > </Canvas> </div> ); } createRoot(window.root).render(<App />); </script> </body> </html>
运行时出现以下错误:
its-fine.development.mjs:68 警告:无效的Hook调用。Hook只能在函数组件的主体内部调用。可能的原因如下: 1. React与渲染器(如React DOM)版本不匹配 2. 违反了Hook的使用规则 3. 应用中存在多个React副本 查看React官方文档的无效Hook调用相关内容获取调试和修复建议。 react.development.js:1650 Uncaught TypeError: Cannot read properties of null (reading 'useMemo') at Module.useMemo2 (react.development.js:1650:21) at Canvas (react-three-fiber.esm.js:125:9) at renderWithHooks (react-dom.development.js:16305:18) at updateForwardRef (react-dom.development.js:19226:20) at beginWork (react-dom.development.js:21636:16) at HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:16) at invokeGuardedCallback (react-dom.development.js:4277:31) at beginWork$1 (react-dom.development.js:27451:7) at performUnitOfWork (react-dom.development.js:26560:12) its-fine.development.mjs:68 上述错误发生在<ForwardRef(Canvas)>组件中: at Canvas (https://esm.sh/v135/@react-three/fiber@8.16.6/es2022/fiber.development.mjs:2015:3) at FiberProvider (https://esm.sh/v135/its-fine@1.2.5/es2022/its-fine.development.mjs:71:21) at CanvasWrapper at div at App 建议在组件树中添加错误边界来自定义错误处理行为。 访问React官方文档的错误边界相关内容了解更多信息。
通过浏览器Sources面板发现,页面同时加载了React v18.2.0和v18.3.1两个版本,推测这是导致无效Hook调用错误的原因,请问该如何解决?
(原问题附带CodeSandBox示例)
解决方案
核心是强制所有依赖统一使用同一个React版本,避免多副本冲突,具体调整如下:
完善Import Map,锁定React版本
原import map只定义了部分包,需要添加react和react-dom的直接映射,同时强制@react-three/fiber依赖指定版本的React,修改后的import map如下:<script type="importmap"> { "imports": { "react": "https://esm.sh/react@18.2.0?dev", "react-dom": "https://esm.sh/react-dom@18.2.0?dev", "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?dev", "@react-three/fiber": "https://esm.sh/@react-three/fiber@8.16.6?dev&deps=react@18.2.0,react-dom@18.2.0" } } </script>这样可以避免依赖自动拉取最新版React,确保所有模块共用同一个18.2.0版本。
修正ReactDOM挂载目标
原代码中createRoot(window.root)的写法错误,应该通过DOM API获取挂载节点:createRoot(document.getElementById('root')).render(<App />);调整JSX导入源
原import map中的@jsxImportSource写法不正确,可在模块脚本顶部添加注释指定JSX编译源:/** @jsxImportSource react */ import {createRoot} from 'react-dom/client'; import {Canvas} from '@react-three/fiber';验证版本一致性
修改后刷新页面,在浏览器Sources面板中检查React版本,确认只有18.2.0一个版本被加载,此时Hook调用错误即可解决。
内容的提问来源于stack exchange,提问作者The Prenx
相关产品推荐
相关产品推荐

