react 在 componentWillMount() 中調用異步函數時,componentWillMount() finishes after render()


剛開始使用 react,很多屬性、方法不是很熟。在此記錄下我所遇到的問題及解決方法。

我在 componentWillMount() 中調用了一個異步函數,在返回結果中調用 this.setState() 來保存數據,在 render() 中使用 this.state.article 時,顯示為 undefined。代碼如下:

componentWillMount() {
  console.log('componentWillMount called')
  let _ = this

  // 獲取當前文章 ID;
  let postID = utils.getID(ARTICLE)
 
  /**
   * @description 獲取、渲染文章內容
   * @param {Number} postID - 當前文章 ID
   */
  postIO.getDetail(postID).then(res => {
    if (res.status === 200) {
      console.log('asynchronous called')
      let data = res.data
 
      _.setState({
        article: {...data},
              })
          }
  })
}
 
render() {
  console.log('render called')
  return (
    <div></div>
  )
}
 
可以看到控制台打印信息:
componentWillMount called
render called
asynchronous called
render called
 
這里可以得出:調用完 componentWillMount() 后,執行 render(),這時 componentWillMount 中的回調函數也執行完畢,更新數據后再次調用 render。
 
這個問題原因:首先,異步函數本身就是不會等前一個任務結束后再執行后一個函數,而是在執行其回調函數的同時就開始執行后一個函數了。因此,在調用完 componentWillMount 函數后,執行 postIO.getDetail(postID).then(res => {}),同時執行 render()。
 
可能導致的問題:在 componentWillMount 中的回調函數中調用 this.setState({article: {...data}}),第一次調用 render 時,是獲取不到 this.state.article 的值的,這樣就會引起報錯。
 
解決方法:
增加一個加載狀態,默認為 false,調用 componentWillMount() 時,設置為 true,當這個加載狀態是 true 時,暫不渲染,當回調函數執行完畢后,設置為 false,此時再調用 render();
 
完整代碼如下:
constructor(props) {
  super(props)
  
  this.state = {
    article: {},
    isLoading: false,
  }
}
componentWillMount() {
  let _ = this

  // 獲取當前文章 ID;
  let postID = utils.getID(ARTICLE)
 
  _.setState({isLoading: true})
 
  /**
   * @description 獲取、渲染文章內容
   * @param {Number} postID - 當前文章 ID
   */
  postIO.getDetail(postID).then(res => {
    if (res.status === 200) {
      console.log('asynchronous called')
      let data = res.data
 
      _.setState({
        article: {...data},
        isLoading: false
              })
          }
  })
}
 
render() {
  let {isLoading} = this.state
  if (isLoading) {
    return <p>isLoading...</p>
  }
  return (
    <div></div>
  )
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM