React Redux员工数组Props首次为空,添加isLoading后报错求助
嗨,我来帮你一步步解决这两个问题——先搞定那个烦人的TypeError,再实现组件等待数据加载完成后再渲染的需求。
一、先修复Reducer的TypeError错误
你遇到的错误提示是assign的源必须是对象,本质是因为reducer状态结构不统一,加上mapStateToProps的逻辑没跟上结构变化导致的,我们来调整:
1. 规范Reducer的初始状态与更新逻辑
原来的初始状态是空对象,现在要明确包含isLoading和员工列表的结构,确保每次更新状态都返回完整的对象:
import { EMPLOYEES_FETCH_SUCCESS, USER_ADD } from "../actions/types"; // 明确初始状态:默认加载中,列表为空数组 const INITIAL_STATE = { list: [], isLoading: true }; export default (state = INITIAL_STATE, action) => { switch (action.type) { case EMPLOYEES_FETCH_SUCCESS: // 用扩展运算符保留原有状态,只更新需要修改的属性 return { ...state, list: action.payload, isLoading: false }; case USER_ADD: return state; default: return state; } };
2. 同步调整mapStateToProps的逻辑
现在state.employees是包含list和isLoading的对象,要对应修改映射逻辑,同时把isLoading也传到组件props里:
const mapStateToProps = state => { // 从state.employees.list里取数组进行处理 const employees = _.map(state.employees.list, (val, uid) => { return { ...val, uid }; }); return { employees, isLoading: state.employees.isLoading // 把加载状态传给组件 }; };
之前的错误就是因为修改reducer后,state.employees结构变了,但mapStateToProps还在直接处理它,导致_.map拿到的不是数组,进而触发了对象赋值的错误。
二、实现组件等待数据加载完成后再渲染
现在我们已经把isLoading状态传到组件了,接下来在render方法里根据状态判断显示内容:
1. 修改组件的render方法
加载状态下显示加载提示,数据准备好后再渲染ListView:
render() { // 如果还在加载中,显示加载提示 if (this.props.isLoading) { return ( <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <Text>正在加载员工数据...</Text> </View> ); } console.log(this.props.employees); return ( <View> <ListView style={styles.listStyle} enableEmptySections dataSource={this.dataSource} renderRow={this.renderRow} /> <Button onPress={this.onButtonPress.bind(this)}>Group chat</Button> </View> ); }
2. 优化生命周期方法(可选但推荐)
componentWillMount和componentWillReceiveProps在新版本React中已经被标记为过时,建议换成更安全的生命周期:
componentDidMount() { this.props.employeesFetch(); this.createDataSource(this.props); } // 当props变化时更新数据源 componentDidUpdate(prevProps) { if (prevProps.employees !== this.props.employees) { this.createDataSource(this.props); } }
3. 给createDataSource加边界保护
避免employees为空时cloneWithRows报错:
createDataSource({ employees }) { const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); // 确保传入的是数组,空数组也能正常处理 this.dataSource = ds.cloneWithRows(employees || []); }
三、最后验证数据传递
确认你的action dispatch里的returnArray是一个数组(就像你截图里的结构那样),这样reducer里的list才能拿到正确的数组类型,后续的映射逻辑才能正常工作:
dispatch({ type: EMPLOYEES_FETCH_SUCCESS, payload: returnArray });
这样调整后,不仅能修复那个TypeError,还能让组件在数据加载完成前显示友好的加载提示,直到数据准备好再渲染员工列表。
内容的提问来源于stack exchange,提问作者Andy Alexander

