React + Easy Peasy 出现 TypeError: enrolment[1] is undefined 问题求助
解决React + Easy Peasy启动时数据未加载导致的TypeError问题
我太懂你遇到的这个坑了!启动时直接崩,热更新反而正常,本质就是组件首次渲染时,Easy Peasy的store里还没拿到API返回的数据——你的enrolment初始是个空数组[],直接去访问enrolment[1].steps[1][0].heading1.label肯定会炸,因为enrolment[1]是undefined,再往下访问属性就触发TypeError了。热更新时API请求已经完成,store里有数据了,所以就正常运行了。
下面给你几个实用的解决办法,按优先级推荐:
1. 最快捷:用可选链操作符避免层级访问报错
ES6+的可选链?.可以帮你在访问嵌套属性时,只要某一层是undefined/null就直接返回undefined,不会抛出错误。直接修改你的渲染代码:
return ( <> <Banner /> {enrolment[1]?.steps[1]?.[0]?.heading1?.label || '加载中...'} </> )
这样即使数据还没加载,也只会显示加载中...而不会崩溃,等API返回数据后会自动更新显示正确内容。
2. 条件渲染:明确控制不同状态下的UI
如果不想用可选链,可以先判断enrolment是否有足够的数据,再渲染目标内容,逻辑更直观:
return ( <> <Banner /> {enrolment.length > 1 && enrolment[1].steps?.length > 1 && enrolment[1].steps[1][0] ? ( enrolment[1].steps[1][0].heading1.label ) : ( <div>加载中...</div> )} </> )
3. 规范方案:添加加载/错误状态,提升用户体验
可以在store里新增状态追踪API请求的生命周期,这样组件能清晰处理加载中、加载成功、加载失败三种场景:
第一步:修改enrolmentModel
const enrolmentModel = { /* STATES */ steps: [], isLoading: false, // 新增加载状态 error: null, // 统一管理错误信息 /* THUNKS */ getDataFromAPI: thunk(async (actions) => { try { actions.setLoading(true); // 请求开始时标记为加载中 const { data } = await axios.get(`${API_URL}/steps/?idInstitution=123455`); actions.setDataFromAPI(data); } catch(e) { actions.setError(e); } finally { actions.setLoading(false); // 请求结束(成功/失败)都关闭加载状态 } }), /* ACTIONS */ setLoading: action((state, isLoading) => { state.isLoading = isLoading; }), setError: action((state, error) => { state.error = error.message; console.log(error.message); }), setDataFromAPI: action((state, steps) => { state.steps = steps; }) }
第二步:在Enrolment组件中使用状态
const Enrolment = () => { const enrolment = useStoreState(state => state.enrolmentModel.steps); const getEnrolmentForm = useStoreActions(actions => actions.enrolmentModel.getDataFromAPI); const isLoading = useStoreState(state => state.enrolmentModel.isLoading); const error = useStoreState(state => state.enrolmentModel.error); useEffect(() => { getEnrolmentForm(); },[]); // 处理错误状态 if (error) { return <div>加载失败:{error}</div>; } // 处理加载状态 if (isLoading) { return <div>加载中...</div>; } // 确保数据结构完整再渲染 if (!enrolment[1]?.steps?.[1]?.[0]) { return <div>暂无数据</div>; } return ( <> <Banner /> {enrolment[1].steps[1][0].heading1.label} </> ) };
这种方式最规范,能覆盖所有边缘场景,用户体验也更友好。
总结一下,优先用可选链+加载状态的组合,既解决报错问题,又能给用户清晰的反馈。热更新正常是因为此时store已经有数据了,而首次渲染时数据还在请求中,所以必须处理好初始渲染时的空数据情况。
内容的提问来源于stack exchange,提问作者NatV
相关产品推荐
相关产品推荐

