React类组件:如何等待数据请求完成后再渲染及状态更新不触发重渲染问题
解决方案:React 数据加载与组件渲染问题
看起来你碰到了React异步数据加载和状态更新的典型问题,我来帮你一步步解决:
首先得明确两个核心问题的根源:
- 你直接修改了
this.state.data而不是用React官方的setState方法——这就是数据更新后组件没重新渲染的关键,React不会监听对state的直接赋值,只有通过setState才会触发组件重渲染流程。 - 组件初始化时会立刻执行
render,这时候异步请求还没返回结果,所以表格拿到的是空数组。
问题2的解决:用setState正确更新状态
先修改你的getTableData方法,把直接赋值改成setState:
getTableData() { api.get('/project', {}).then( data => { const {issues, users} = data.project; // 处理表格需要的数据格式 const tableData = issues.map(issue => { const u = users.find(user => user.id === issue.userIds[0]) return [ issue.title, issue.deadline, issue.status, issue.createdAt, (u && u.name) ? u.name : 'Not Assigned' ] }); // 使用setState更新状态,而非直接修改this.state this.setState({ data: tableData }, () => { console.log('check 1: ', this.state.data); // 在setState的回调里确认更新后的状态 }); }, error => { console.log(error); }); }
这样当数据处理完成后,setState会触发组件重新渲染,表格就能拿到最新的数据了。
问题1的解决:添加加载状态,优化渲染逻辑
你不需要完全阻止组件渲染(React也不推荐这么做),而是可以在数据加载完成前显示加载提示,给用户更友好的反馈。步骤如下:
- 在state中添加
loading状态:
constructor(props){ super(props); this.state = { columns: tableColumns, data: [], loading: true // 初始设为加载中 }; this.getTableData(); }
- 请求完成后更新
loading状态:
getTableData() { api.get('/project', {}).then( data => { const {issues, users} = data.project; const tableData = issues.map(issue => { const u = users.find(user => user.id === issue.userIds[0]) return [ issue.title, issue.deadline, issue.status, issue.createdAt, (u && u.name) ? u.name : 'Not Assigned' ] }); // 同时更新数据和加载状态 this.setState({ data: tableData, loading: false }); }, error => { console.log(error); // 请求失败也要关闭加载状态,避免一直显示加载提示 this.setState({ loading: false }); }); }
- 在render中根据
loading状态切换显示内容:
render() { const { columns, data, loading } = this.state; const options = { print: false, download: false, selectableRowsHideCheckboxes: true, selectableRows: 'None', filterType: "textField", responsive: 'stacked', rowsPerPage: 10, page: 1 }; // 加载中时显示提示 if (loading) { return <div>正在加载数据...</div>; // 可以换成更美观的加载组件 } // 数据加载完成后渲染表格 return ( <MUIDataTable title="My Table" data={data} columns={columns} options={options} /> ); }
额外优化建议
- 推荐在
componentDidMount生命周期中调用数据请求,这是React官方建议的异步数据加载时机:
componentDidMount() { this.getTableData(); } constructor(props){ super(props); this.state = { columns: tableColumns, data: [], loading: true }; }
- 为了避免
this指向问题,可以把getTableData绑定到组件实例,或者改用箭头函数写法:
// 方法1:在constructor中绑定 constructor(props){ super(props); // ... this.getTableData = this.getTableData.bind(this); } // 方法2:直接写成箭头函数 getTableData = () => { // 方法内容 }
内容的提问来源于stack exchange,提问作者Kid_Learning_C
相关产品推荐
相关产品推荐

