懒加载React Portal组件时出现Failed to fetch动态导入模块错误
问题分析与解决方案
出现Failed to fetch dynamically imported module错误的核心原因是将React.lazy的导入声明放在了组件内部,每次组件重新渲染(比如showModal状态变化时)都会重新创建懒加载组件实例,触发重复的模块请求,导致浏览器无法正确加载模块。结合Portal组件的渲染逻辑,这种重复请求会引发加载失败。
修复步骤
1. 移懒加载声明到组件外部
将React.lazy的导入语句放在Inbox组件定义之外,确保模块只被请求一次:
import { useState, Suspense, lazy } from 'react'; // 移到组件外部,避免重复导入 const InboxModal = lazy(() => import("../portals/inboxModal")); const Inbox = () => { const [showModal, setShowModal] = useState<boolean>(false); return ( <div className="overflow-x-auto shadow-md sm:rounded-lg justify-center w-full"> <div onClick={() => setShowModal((pre) => !pre)}>点击打开弹窗</div> <Suspense fallback={<div>loading...</div>}> {showModal && <InboxModal />} </Suspense> </div> ); }; export default Inbox;
2. 为Portal组件添加DOM元素存在性检查
虽然portal-root在index.html中已定义,但添加检查可以避免潜在的运行时错误(非本次错误直接原因,但属于最佳实践):
import { createPortal } from 'react'; const InboxModal = () => { const portalDiv = document.getElementById("portal-root"); // 确保目标DOM元素存在 if (!portalDiv) { return null; } return createPortal( <div className="w-1/3 h-2/3 bg-red-400 absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"> <p>hello</p> </div>, portalDiv ); }; export default InboxModal;
原理说明
- React.lazy的导入声明应该是静态的,放在组件外部可以保证模块只被异步加载一次,避免重复请求导致的加载失败。
- Portal组件本身的逻辑没有问题,错误是由懒加载的不当使用引发的,移除Portal后组件简化,重复请求的影响被掩盖,因此能正常工作。
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

