React Redux Reducer无法识别JSON数据引发TypeError问题求助
解决React Redux中Cannot read property 'label' of undefined的问题
你遇到的这个报错,根源其实是数据存储的属性不匹配+初始状态类型错误,再加上组件没处理数据未加载的空白期,咱们一步步拆解修复:
1. 先揪出Reducer里的核心问题
看你的Reducer代码:
DATA_LOADEDaction把请求回来的JSON数据存在了remoteArticles里,但你的组件通过mapStateToProps取的是state.rootReducer.articles——这完全是两个不相关的属性!- 初始状态里
articles被设成了空数组[],但你请求回来的是包含basics节点的对象,数组根本没有.basics属性,这直接触发了报错。
修正Reducer代码
把请求回来的数据存到articles属性里(更符合你的组件逻辑),同时调整初始状态为null(明确表示数据未加载):
import { FOUND_BAD_WORD, DATA_LOADED, ADD_ARTICLE } from '../constants/action-types'; const initialState = { articles: null, // 改成null,匹配后续要存储的对象类型 remoteArticles: [], badword: '', }; export default function reducer(state = initialState, action) { if (action.type === ADD_ARTICLE) { return { ...state, articles: state.articles.concat(action.payload) }; } if (action.type === FOUND_BAD_WORD) { return Object.assign({}, state, { badword: action.payload[0] }); // 简化冗余赋值 } if (action.type === DATA_LOADED) { return { ...state, articles: action.payload }; // 把请求数据存到articles属性 } return state; }
2. 给组件加上加载状态判断
即使修正了Reducer,Redux-Saga完成请求前,articles还是null,直接访问articles.basics依然会报错。所以要在组件里先判断数据是否就绪:
function Hero({ articles }) { // 数据未加载时显示加载提示,避免访问undefined属性 if (!articles) { return <div>Loading...</div>; } return ( <section className="hero is-dark is-fullheight has-bg-image"> <div className="hero-head"> <NavBar /> </div> <div className="hero-body"> <div className="container"> <p className="subtitle is-5 has-text-weight-light">I'm a</p> <h1 className="title">{articles.basics.label}</h1> <h2 className="subtitle"> {articles.basics.location.region}, {articles.basics.location.country} </h2> <div> <p className="subtitle is-5 has-text-weight-light">{articles.basics.description}</p> </div> <div className="navbar-item is-6 is-unselectable">{articles.basics.fansite}</div> <div className="navbar-item is-6 is-unselectable">{articles.basics.fansiteDev}</div> </div> </div> <div className="hero-foot" style={{ paddingBottom: '20px' }}> <div className="columns is-mobile"> <div className="column" /> {/* 用可选链操作符,避免profiles为空时报错 */} {articles.basics.profiles?.map(value => { const id = uniqueId(); return ( <div key={id} className="column has-text-centered"> <a href={value.url} target="blank" className="is-hovered" title={value.network}> <span className="icon is-medium is-"> <i className={value.x_icon} /> </span> </a> </div> ); })} <div className="column" /> </div> </div> <div style={{ position: 'static', color: 'gray', fontSize: '.875rem', }} > <ShowBuildAndVersion /> </div> </section> ); } const mapStateToProps = state => { return { articles: state.rootReducer.articles }; }; const Aaa = connect(mapStateToProps)(Hero); export default Aaa;
3. 可选优化方案
如果你想保留remoteArticles的存储方式,只需要把mapStateToProps改成:
const mapStateToProps = state => { return { articles: state.rootReducer.remoteArticles }; };
同时把initialState里的remoteArticles设为null,组件里的加载判断逻辑不变即可。
这样修改后,就能彻底解决你遇到的TypeError问题了。
内容的提问来源于stack exchange,提问作者Kid
相关产品推荐
相关产品推荐

