Reactjs调用threads.map时报Cannot read properties of undefined错误如何解决
报错原因
- 核心原因是你调用
map方法的this.props.threads为undefined,只有数组类型支持map方法,非数组类型调用会抛出该错误,具体触发场景分三类:- 首次页面渲染时,还未收到后端WebSocket返回的线程数据,Reducer初始状态未给
threads设置默认空数组,此时this.props.threads取值为undefined - 数据链路取值错误:后端返回的消息结构中
data字段直接对应线程数组,如果Action中取值为data.data,相当于读取数组本身不存在的data属性,最终存入Reducer的threads为undefined - 后端查询异常时没有返回兜底空数组,导致前端从未收到线程数据,
threads始终为初始的undefined
- 首次页面渲染时,还未收到后端WebSocket返回的线程数据,Reducer初始状态未给
修复方案
1. 给Reducer添加初始默认值
给Reducer的初始状态设置threads默认值为空数组,保证首次渲染时threads一定是数组类型:
// 定义初始状态 const initialState = { threads: [], // 保留你原有其他state属性 } function threadReducer(state = initialState, action) { switch(action.type) { case "INITIAL_THREADS": return { ...state, threads: action.payload } // 保留你原有其他case逻辑 default: return state } }
2. 修正Action层的取值逻辑
确认后端返回的消息结构后,修正payload的取值,不要多取一层.data:
case 'INITIAL_THREADS': dispatch({ type: 'INITIAL_THREADS', payload: data, // 原代码为data.data,去掉多余的.data层 });
如果你接收WS消息时已经做过一层解析,
data本身是后端返回的data字段对应值,可以保留原有取值,只需要确保最终payload是数组类型即可。
3. 渲染层添加容错判断
在调用map前添加可选链或者空数组兜底,避免极端情况报错,同时给循环的li元素添加key属性消除React警告:
<ul className="thread-list"> <label>Messages</label> { this.props.threads?.map((thread, threadIndex) => { return( <li key={threadIndex}> <Link to={`/${thread.id}`}> <i className="zmdi zmdi-account-circle" /> <h5>{thread.id}</h5> <p>This is the last message</p> </Link> </li> ); }) } </ul>
不支持可选链语法的环境可以替换为
(this.props.threads || []).map
4. 后端添加返回兜底逻辑
后端查询线程列表时,不管是否查询成功都返回消息,异常场景兜底返回空数组:
ws.on('connection', (ws) => { function getInitialThreads(userId){ models.Thread.find({ where: {}}, (err, threads) => { const resThreads = !err && threads ? threads : [] ws.send(JSON.stringify({ type: 'INITIAL_THREADS', data: resThreads, })); }); } })
内容的提问来源于stack exchange,提问作者Shagun Raghav
相关产品推荐
相关产品推荐

