React Redux Toolkit页面刷新后出现Cannot read properties错误
问题分析与解决方案
核心原因
刷新页面后抛出Cannot read properties of undefined (reading 'length')错误,主要源于以下几点:
- Thunk静态读取Cookie:
menuSlice.js中title和token在模块初始化时获取,页面刷新时可能存在Cookie未及时读取的情况,导致API请求URL异常,最终返回的payload为undefined,state.menu被赋值为undefined。 - Loading状态逻辑漏洞:初始
status设为false,页面刷新后首次渲染会直接加载Menu组件,若API请求未完成或失败,menu可能变为undefined,组件访问length时触发错误。 - 未处理请求失败场景:请求被拒绝时未重置
menu为默认数组,若menu已被错误赋值为undefined,会导致后续渲染出错。
修复方案
1. 动态在Thunk内获取Cookie
将Cookie读取逻辑移到fetchMenu内部,确保每次调用Thunk时都能获取最新的Cookie值,同时增加空值校验:
// menuSlice.js export const fetchMenu = createAsyncThunk("getMenuItems/title", async () => { const cookies = new Cookies(); const title = cookies.get('title'); const token = cookies.get('token'); if (!title || !token) { return []; } const url = `https://xxxxxxxx/getMenuItems/${title}`; const data = await axios.get(url, { headers: { Authorization: `Bearer ${token}` }, }); return Array.isArray(data.data) ? data.data : []; });
2. 优化Loading初始状态
将initialState中的status设为true,确保页面首次加载时直接显示Loading,避免提前渲染依赖数据的组件:
// menuSlice.js export const menuSlice = createSlice({ name: "menu", initialState: { menu: [], status: true, // 初始设为加载中 }, extraReducers: { [fetchMenu.pending]: (state) => { state.status = true; }, [fetchMenu.fulfilled]: (state, action) => { state.status = false; state.menu = action.payload; }, [fetchMenu.rejected]: (state) => { state.status = false; state.menu = []; // 请求失败时重置为数组 }, }, });
3. 组件内增加空值防护
在Menu组件中对siteData进行空值检查,避免直接访问length:
// Menu组件示例 function Menu({ siteData = [], siteId }) { // 使用可选链或默认值处理空值 const itemCount = siteData?.length || 0; if (!siteData || siteData.length === 0) { return <div>暂无菜单数据</div>; } // 后续渲染逻辑 }
4. 完善Home页面渲染逻辑
传递数据时增加默认值,确保组件始终收到数组类型的参数:
// Home页面 return ( <div className="row d-flex w-100 h-100 justify-content-center mx-auto px-0 "> <div className="row d-flex col-md-9 col-lg-9 justify-content-center col-sm-12 mx-auto px-0"> <div className="col-md-5 col-lg-5 col-sm-12"> <Menu siteData={menu || []} siteId={title} /> </div> <div className="col-md-7 col-lg-7 col-sm-12 bg-light "> <Edit siteData={menu || []} siteId={title} /> </div> </div> <div className="col-md-3 col-lg-3 col-sm-12 "> <input onClick={logOut} type="button" name="" id="" value="LogOut" /> </div> </div> );
内容的提问来源于stack exchange,提问作者Sarmed MQ Berwari
相关产品推荐
相关产品推荐

