React渲染前Fetch数据报错:map遍历未加载数据问题
解决React中Fetch数据未加载完成时调用map报错的问题
我明白你遇到的问题了——组件渲染的时候,this.props.beers还没从API请求回来,这时候直接调用map就会报错,而点击事件是在数据加载完成后触发的,所以能正常拿到数据。咱们一步步来解决这个问题:
问题根源
你的Reducer初始状态设为了null:
export default function(state=null, action){ switch(action.type){ case FETCH_BEERS: return action.payload; default: return state; } }
组件首次渲染时,this.props.beers是null,而null上没有map方法,自然会报错。而点击事件触发时,API请求已经完成,beers已经是数组了,所以能正常访问元素。
解决方案
1. 把Reducer的初始状态改为空数组
这是最基础的修复,让初始状态变成一个空数组,这样即使数据还没加载,调用map也不会报错(空数组的map会返回空数组,不会抛出错误):
export default function(state=[], action){ // 这里把null改成[] switch(action.type){ case FETCH_BEERS: return action.payload; default: return state; } }
2. 利用loading状态做条件渲染
你的组件已经有loading这个props了,正好可以用它来在数据加载中显示提示,加载完成后再渲染啤酒列表,提升用户体验:
修改BeersLanding组件的render部分:
render(){ const {loading, beers} = this.props; console.log(beers) return( <div style={{textAlign:'center'}}> ... <input type="text" placeholder="Search.." name="search"></input> <button type="submit" onClick={() =>this.getBeers()} >Submit</button> <div className={'beersContainer'}> {/* 加载中显示提示 */} {loading ? ( <p>加载中...</p> ) : ( {/* 加载完成后渲染列表 */} beers.map((beer,index)=>( <div className={'card'} key={index}> {/* 记得加key属性避免React警告 */} hello </div> )) )} </div> </div> ); }
3. 可选:添加空值判断(兜底方案)
如果不想修改Reducer初始状态,也可以在调用map前先判断beers是否存在且是数组,做一层兜底:
{beers && beers.length > 0 ? ( beers.map((beer,index)=>( <div className={'card'} key={index}> hello </div> )) ) : loading ? ( <p>加载中...</p> ) : ( <p>暂无啤酒数据</p> )}
额外优化建议
父组件里的异步请求最好放在componentDidMount生命周期里,而不是constructor中,这是React官方推荐的异步请求时机:
class App extends Component{ componentDidMount() { this.props.fetchUser(); this.props.fetchBeers(); } // ...其他代码 }
这样修改后,就能彻底避免数据未加载完成时调用map的错误,同时用户也能看到清晰的加载状态,体验更流畅。
内容的提问来源于stack exchange,提问作者Dave_888
相关产品推荐
相关产品推荐

