首页 > 解决方案 > 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;

标签: javascriptreactjs

解决方案


好吧,我想到了很多事情。

首先,只有当你有两条数据之一时才将 isLoading 设置为 false,以先到者为准,因此 render 方法将在某些时候以空比赛或结果调用你的函数。另一件事,您正在异步调用 setState。到请求完成时,您的组件可能不再存在,因此它将尝试更新不存在的组件并因该错误而失败。

对于第一个问题,一个可能的解决方案是为结果和比赛设置两个 isLoading 变量。

对于第二个问题(在 unmountedComponent 上调用 setState),它有点复杂,因为您需要以某种方式取消请求。我建议阅读更多关于此的内容,一般建议是使用 redux 之类的库将数据从组件中移出。如果你谷歌cancel promise on unmount你会发现关于这个的讨论。您还可以使用“isMounted”变量来处理它,这将作为一个丑陋的补丁。

因此,一旦请求一(或二)完成,就会调用 setState,然后重新渲染组件。isLoading 现在为真,因此 filterAndSort 被调用结果(或比赛)但不是两者都因为第二个请求仍在等待中。

最后,在您的渲染方法中,您的 isLoading 需要首先定义(我假设它在您的代码中但不是在问题中)并且 is True 比较可以更好地放置为

if (isLoading) {代替if (isLoading == True) {


推荐阅读