React Native使用Redux+Axios时首次启动报undefined,state加载过慢
问题修复方案
核心问题原因
- 变量名冲突+暂时性死区报错:props传入的参数命名为
data,后续又在组件内声明同名const data,在声明这个变量的内部访问data.users时,会优先指向未完成初始化的本地data变量,触发暂时性死区规则直接返回undefined。 - 初始状态无兜底,未处理异步请求前的空状态:reducer初始
state.data是空对象,首次渲染时请求还未返回,data.users本身就是undefined,直接调用map方法必然报错。 - Reducer状态更新遗漏:
GET_DATA_SUCCESS和GET_DATA_FAILURE分支没有将loading重置为false,导致无法通过loading状态判断请求是否完成。 - 未做加载状态拦截:组件渲染时没有判断loading状态,请求完成前就直接渲染了需要完整数据的图表组件。
之前删除代码等加载完成再粘贴就正常,是因为此时请求已经返回,data.users已经被赋值,组件重新渲染时不会碰到初始空状态的问题。
修复步骤
1. 调整reducer逻辑
补充loading状态重置,提前初始化兜底字段:
const initialState = { data: { users: [] // 提前初始化users空数组兜底 }, error: null, loading: false } const xchReducer = (state = initialState, action) => { switch (action.type) { case xchActions.GET_DATA_BEGIN: return { ...state, loading: true } case xchActions.GET_DATA_SUCCESS: return { ...state, loading: false, // 请求成功重置loading data: action.payload.data } case xchActions.GET_DATA_FAILURE: return { ...state, loading: false, // 请求失败重置loading error: action.payload.error } default: return state } } export default xchReducer;
2. 调整Home组件逻辑
修改冲突变量名,增加状态拦截判断,补充空值兜底:
const Home = ({ getData, data, loading, // 解构拿到loading状态 error }) => { useFocusEffect( React.useCallback(() => { getData() }, []) ) function renderHeaderContent() { return ( <View style = {{ flexDirection: 'row', justifyContent: 'flex-start', ...Platform.select({ ios: { paddingTop: 40 } }) }}> <View style = {{ marginTop: 10, justifyContent: 'center', alignItems: 'center', alignContent: 'center', flex: 1 }}> {/* userName加可选链兜底,避免空值报错 */} <Text> {data?.userName || ''} </Text> </View> </View> ) } // 变量名不要和props的data重名,改为chartData,加可选链兜底 const chartData = { datasets: [{ // 可选链+兜底空数组,避免undefined调用map data: [...(data?.users?.map(d => d.points) || [])], strokeWidth: 2 }] }; function renderChartContent() { // 加载中或者数据为空时显示占位内容,避免渲染空图表报错 if(loading || !data?.users?.length) { return <View style={{width: screenWidth, height:256, justifyContent:'center', alignItems:'center'}}> <Text>加载中...</Text> </View> } return ( <View> <LineChart data = {chartData} width = {screenWidth} height = {256} verticalLabelRotation = {30} chartConfig = {chartConfig} withInnerLines = {0} bezier /> </View> ) } // 增加错误状态处理 if(error) { return <View style={{flex:1, justifyContent:'center', alignItems:'center'}}> <Text>加载失败,请稍后重试</Text> </View> } return ( <View style = {{ flex: 1, backgroundColor: COLORS.white }}> {renderHeaderContent()} {renderChartContent()} </View> ) } function mapStateToProps(state) { return { data: state.xchReducer.data, error: state.xchReducer.error, loading: state.xchReducer.loading, } } function mapDispatchToProps(dispatch) { return { getData: () => { return dispatch( getData() ) } } } export default connect(mapStateToProps, mapDispatchToProps)(Home);
内容的提问来源于stack exchange,提问作者Joseph C
相关产品推荐
相关产品推荐

