javascript - ReactJS:多个 setStates 异步发生,状态未更新
问题描述
在触发位于渲染中的函数 (filterAndSort) 之前,面临状态未更新的问题。我在函数中添加了一个 console.log 语句,并且只有一个状态得到更新。我的代码对我来说似乎是合乎逻辑的,因为我设置了一个 if 条件,其中仅在 setState 发生后触发函数
完整的错误信息:
警告:无法在未安装的组件上调用 setState(或 forceUpdate)。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。
但是,我怀疑这是因为我有多个 setStates 异步发生。
我在想,也许,只有在获取所有 axios 请求后,我才需要为所有变量重写 componendDidMount 到 setState 。 多个 Axios 请求进入 ReactJS 状态
我认为另一种解决方案是将函数的返回结果存储为状态而不是变量,然后添加一个componentDidUpdate。
componentDidUpdate(prevProps, prevState) {
if (this.state.value > prevState.value) {
this.filterAndSort();
}
}
零件
class Results extends Component {
constructor(){
super()
this.state = {
results: [],
races: [],
arr = []
isLoading: true
};
}
componentDidMount(){
const oneRequest = axios.get(URL_ONE)
.then(response =>
response.data.data.map(result => ({...
))
)
.then(results => this.setState({results, isLoading: false}))
const twoRequest = axios.get(URL_TWO)
.then(response =>
response.data.data.map(race => ({...}))
)
.then(races => this.setDefault(races))
}
setDefault = (races) => {
........
this.setState({arr, races, isLoading:false})
}
filterAndSort = (races, results) => {
console.log(races, results)
.......
}
render() {
const{races, results} = this.state
if (isLoading == true) {
return (
<div>
<p>Loading...</p>
</div>
)
} else {
return (
<div>
<BarChart
qualData={this.filterAndSort(races, results)}
raceData={this.filterAndSort(races, results)}
width="1200"
height="500" />
</div>
);
}
}
}
export default Results;
解决方案
好吧,我想到了很多事情。
首先,只有当你有两条数据之一时才将 isLoading 设置为 false,以先到者为准,因此 render 方法将在某些时候以空比赛或结果调用你的函数。另一件事,您正在异步调用 setState。到请求完成时,您的组件可能不再存在,因此它将尝试更新不存在的组件并因该错误而失败。
对于第一个问题,一个可能的解决方案是为结果和比赛设置两个 isLoading 变量。
对于第二个问题(在 unmountedComponent 上调用 setState),它有点复杂,因为您需要以某种方式取消请求。我建议阅读更多关于此的内容,一般建议是使用 redux 之类的库将数据从组件中移出。如果你谷歌cancel promise on unmount
你会发现关于这个的讨论。您还可以使用“isMounted”变量来处理它,这将作为一个丑陋的补丁。
因此,一旦请求一(或二)完成,就会调用 setState,然后重新渲染组件。isLoading 现在为真,因此 filterAndSort 被调用结果(或比赛)但不是两者都因为第二个请求仍在等待中。
最后,在您的渲染方法中,您的 isLoading 需要首先定义(我假设它在您的代码中但不是在问题中)并且 is True 比较可以更好地放置为
if (isLoading) {
代替if (isLoading == True) {
推荐阅读
- processing - 处理:将绘图循环运行到一个独立的线程中
- android - 从android中的另一个应用程序共享时如何检索链接?
- javascript - 无法使用 Selenium Webdriver (Node JS) 登录网站
- reactjs - 点击一个元素触发点击另一个元素
- javascript - Json 未在 FullCalendar 中加载
- python - AWS Lambda 中的 FFMPEG 只会输出 5 秒的转换视频
- python - 为什么即使我已指定我的链表遍历终止,我也会收到超时错误?
- amazon-web-services - 将 sql 转储文件从 EC2 复制到 RDS 数据库时出现“1046 No Database Selected”错误
- amazon-s3 - 在 EC2 中使用 AWS S3 文件网关,为什么它只能在公有子网中工作,而不能在私有子网中工作?
- maven - PMD - maven、sonarqube 和 java 版本之间的混淆