NextJS+React项目首屏报Cannot read 'map'错误,强制刷新后正常
问题原因
你遇到的错误核心是运行时存在数组类型变量为undefined的情况下执行了map方法,强制刷新生效的核心原因是跳过了客户端缓存,消除了水合不匹配或者旧缓存数据异常的问题,具体根因集中在以下几点:
- 水合不匹配:useSWR默认仅在客户端执行,服务端渲染时组件会直接返回
loading文本,若客户端存在旧的SWR缓存,首次渲染时直接读取缓存数据渲染DashboardPage,和服务端返回的loading结构不一致,触发水合异常导致不可预期的变量undefined问题。 - 入参容错不足:你当前给DashboardPage传参使用的
data?.xxx && data.xxx写法,只会返回原数据或者false/undefined,若接口返回对应字段不是数组类型,子组件拿到的还是非数组值,即使加了可选链也可能因为逻辑漏洞触发map调用。 - 构建期边界未处理:getStaticPaths中直接访问
data[0],如果接口返回空数组,data[0]为undefined,遍历逻辑异常,同时tables数组为空时虽然map本身不会报错,但如果后续逻辑依赖其返回值也可能出现问题。 - getStaticProps返回的初始数据完全未被使用,白白浪费了服务端提前拉取的数据,也失去了避免客户端首屏无数据的作用。
解决方案
1. 修复参数传递,统一设置空数组默认值
将DashboardPage的传参改为空值合并的写法,保证传入的数组类型参数永远是数组:
<DashboardPage orders={data?.showItemsOnOrder ?? []} dashboardCards={data?.dashboardCardInfo ?? []} ordersGraph={data?.dashboardGraph ?? []} />
2. 给useSWR添加初始值,解决水合问题
将getStaticProps返回的restaurantData作为useSWR的初始回退数据,保证服务端和客户端首次渲染内容一致:
const {data, error} = useSWR("data", fetcher, { fallbackData: props.restaurantData });
3. 补充getStaticPaths的边界判断
避免接口返回空数组时出现的undefined访问问题,同时替换var为let避免变量提升漏洞:
export async function getStaticPaths() { const response = await fetch(`API`); const data = await response.json(); // 补充非空判断 if (!Array.isArray(data) || data.length === 0) { return { paths: [], fallback: false, }; } const tables = []; for (let i = 1; i <= data[0].restaurantTables; i++) { tables.push({ restaurant: data[0].queryName, tableNr: i.toString(), }); } return { paths: tables.map((table) => { return { params: { restaurantName: table.restaurant, tableNr: table.tableNr, }, }; }), fallback: false, }; }
4. 排查子组件map调用
确认所有map调用前都加了可选链,或者提前对遍历对象做数组类型校验,比如:
// 优先用类型校验写法 Array.isArray(orders) && orders.map(item => <div key={item.id}>{item.name}</div>) // 或者可选链写法 orders?.map(item => <div key={item.id}>{item.name}</div>)
内容的提问来源于stack exchange,提问作者Floky99
相关产品推荐
相关产品推荐

