为什么React未渲染更新后的state?异步操作后渲染旧数据如何解决
问题根因
- 异步执行顺序错误:你代码中的
get方法是异步函数,在getNewOrders中遍历调用this.get(a)时没有等待所有异步请求执行完成,就直接触发了setState。此时data数组中的item、buyer字段还未被修改,state中存储的是未处理的原始数据,所以渲染出来的是旧数据。 - 控制台打印的假象:你打印的是引用类型的数组,浏览器控制台对引用类型的打印不会保存执行时刻的快照,当你点开查看打印内容时,异步的
get请求已经执行完成并修改了数组元素,所以你看到的是更新后的值,和实际setState时的真实值不一致。
解决方案
等待所有关联数据的异步请求全部完成后,再调用setState更新state,你可以用Promise.all批量等待所有异步任务执行完成:
// 修改后的getNewOrders方法 getNewOrders = async () => { let data = await api.get(`SellerOrdersAPI/${store.getState().auth.user.id}/`).then(({data})=>data); // 等待所有订单的关联数据查询、修改完成 await Promise.all(data.map(a => this.get(a))) // 数据处理完毕后再更新state this.setState({NewOrders:data}) }
优化建议
为了避免直接修改原数据产生的不可预期副作用,更符合React不可变数据的使用规范,你可以调整get方法返回处理后的新对象,而不是直接修改传入的原对象:
// 修改后的get方法,返回新对象不修改原引用 get = async(a) => { let data1 = await itemApi.get(`/${a.item}/`).then(({data})=>data); let data2 = await userApi.get(`/${a.buyer}/`).then(({data})=>data); return { ...a, item: data1.title, buyer: data2[0].first_name + ' ' + data2[0].last_name } } // 对应调整getNewOrders方法 getNewOrders = async () => { let originData = await api.get(`SellerOrdersAPI/${store.getState().auth.user.id}/`).then(({data})=>data); const processedData = await Promise.all(originData.map(a => this.get(a))) this.setState({NewOrders: processedData}) }
内容的提问来源于stack exchange,提问作者user16137336
相关产品推荐
相关产品推荐

