NextJS 12嵌套动态导入报错:[object Promise]非有效React子元素
解决NextJS 12嵌套动态导入导致的React子元素错误
你的问题核心是组件直接返回了Promise——NextJS12的客户端渲染模式下,React组件必须同步返回JSX/Null,不能返回Promise(NextJS13的服务端组件支持异步返回,但12的客户端组件不支持)。另外你原来的代码还有两个关键问题:
themeObject.works.map里没有返回import()的Promise,导致Promise.all实际等待的是空数组,会直接进入后续then逻辑,此时workNav还没填充数据- 用全局变量
workNav收集JSX,在异步逻辑中修改会导致状态不同步
下面是修正后的代码,结合useState和useEffect正确处理异步加载:
import { useState, useEffect } from 'react'; import Link from 'next/link'; export default function Main() { // 用状态管理导航项和加载状态 const [workItems, setWorkItems] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const loadNavData = async () => { try { // 第一步:导入theme模块 const { default: themeObject } = await import(`./${theme}.mjs`); // 第二步:批量导入所有work模块,注意map要返回Promise const workPromises = themeObject.works.map(async (work, index) => { const { default: workObject } = await import(`./${work}.mjs`); // 直接返回组装好的JSX元素,不用全局数组 return ( <li key={`${work}-${index}`}> <Link href={`${themeObject.theme}/${work}`}> {work} | {workObject.message} </Link> </li> ); }); // 等待所有work模块加载完成,得到完整的JSX数组 const navItems = await Promise.all(workPromises); setWorkItems(navItems); } catch (err) { console.error('加载导航数据失败:', err); } finally { setIsLoading(false); } }; loadNavData(); }, [theme]); // 依赖theme,当theme变化时重新加载 // 渲染时处理加载状态,避免返回空或错误内容 if (isLoading) { return <div>加载中...</div>; } return ( <ul className="text-align-center"> {workItems} </ul> ); }
关键修改点说明:
- 用
useState维护workItems(导航JSX数组)和isLoading状态,替代全局变量workNav,确保状态变化能触发组件重新渲染 - 在
useEffect中封装异步加载逻辑,保证组件初始渲染时返回合法的JSX(加载提示) themeObject.works.map返回async函数(本质是Promise),让Promise.all能正确等待所有模块加载完成- 错误处理:添加
try/catch捕获导入失败的情况,避免页面崩溃 - 依赖数组加入
theme,当theme动态变化时,会重新执行加载逻辑
你之前的useEffect方案失败,是因为只处理了第一层导入,没正确处理嵌套的批量导入,而且没有把最终生成的JSX数组存入状态,直接返回的data要么是未处理的Promise,要么是不符合渲染要求的结构,导致React无法识别。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

