1. 程式人生 > >30天入坑React ---------------day07 Lifecycle Hooks

30天入坑React ---------------day07 Lifecycle Hooks

這篇文章是30天React系列的一部分 。

在本系列中,我們將從非常基礎開始,逐步瞭解您需要了解的所有內容,以便開始使用React。如果您曾經想學習React,那麼這裡就是您的最佳選擇!

下載免費的PDF

30天的React Mini-Ebook

生命週期鉤子

在Github上編輯此頁面

今天,我們將介紹一些我們可以與React元件一起使用的最常見的生命週期鉤子,我們將討論它們為什麼有用以及何時應該使用它們。

恭喜!我們已經在React的第一週結束了,我們已經覆蓋了很多。我們剛剛完成了有狀態元件的工作,以跟蹤元件的內部狀態。今天,我們將暫停實現,並談談元件如何存在於應用程式中。也就是說,我們將討論元件的生命週期。

當React安裝我們的應用程式時,它為我們提供了一些鉤子,我們可以在元件的生命週期中的不同時間插入我們自己的功能。為了掛鉤生命週期,我們需要在我們的元件上定義函式,React在適當的時候呼叫每個鉤子。讓我們深入瞭解第一個生命週期鉤子:

componentWillMount() / componentDidMount()

當在我們的應用程式的頁面上定義元件時,我們不能立即依賴它在DOM中可用,因為我們正在定義虛擬節點。相反,我們必須等到元件本身實際安裝在瀏覽器中。對於我們在安裝時需要執行的功能,我們可以獲得兩個不同的鉤子(或函式)。在元件之前呼叫的一個是在頁面上安裝的,另一個是在元件安裝之後呼叫的。

什麼mounting意思?

由於我們使用React在DOM樹中定義節點的虛擬表示,我們實際上並沒有定義DOM節點。相反,我們正在建立React為我們維護和管理的記憶體檢視。當我們談論安裝時,我們討論的是將虛擬元件轉換為React放置在DOM中的實際DOM元素的過程。

這對於諸如獲取資料以填充元件之類的內容非常有用。例如,假設我們想要使用我們的活動跟蹤器來顯示github事件。我們只想在要呈現資料本身時載入這些事件。

回想一下,我們Content在活動列表中定義了我們的元件:

class Content extends React.Component {
  render() {
    const {activities} = this.props; // ES6 destructuring

    return (
      <div className="content">
        <div className="line"></div>

        {/* Timeline item */}
        {activities.map((activity) => (
          <ActivityItem
            activity={activity} />
        ))}

      </div>
    )
  }
}

讓我們更新Content元件以向github.com事件api發出請求,並使用響應來顯示活動。因此,我們需要更新state物件。

 

 

正如我們昨天所做的那樣,讓我們 通過設定this.state建構函式中的物件來更新我們的元件是有狀態的

class Content extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      activities: []
    }
  }

  // ...
}

現在,我們將要在元件本身準備好安裝時(或者在安裝之後)發出HTTP請求。通過在我們的元件中定義函式componentWillMount()(或componentDidMount()),React在它安裝到DOM之前執行該方法。這是我們新增GET請求的最佳位置。

讓我們Content用github api的請求更新元件。由於我們只想顯示一個小列表,讓我們來看看最新的四個事件。

我們已經儲存了一個github資料的靜態JSON檔案,我們將直接從原始碼載入(我們將在幾天後回到發出AJAX請求)使用promises。現在,讓我們關注如何使用新資料實現更新元件:

class Content extends React.Component {
  // ...
  componentWillMount() {
    this.setState({activities: data});
  }
  // ...
}

請注意,我們沒有更改Content元件中的任何其他內容,它只是起作用。

 

componentWillUpdate() / componentDidUpdate()

有時我們會在更改實際渲染之前或之後更新元件的某些資料。例如,假設我們想呼叫一個函式來設定渲染,或者在元件的props改變時呼叫一個函式集。該componentWillUpdate()方法是一個合理的鉤子來處理準備我們的元件進行更改(只要我們不呼叫this.setState()它來處理它,因為它會導致無限迴圈)。

由於我們不需要深入處理這個問題,我們不會擔心在這裡建立一個例子,但知道它存在是很好的。我們將使用的一個更常見的生命週期鉤子是componentWillReceiveProps()鉤子。

componentWillReceiveProps()

當元件即將接收新的時,React將呼叫方法props。這是第一個在元件要接收一組新道具時呼叫的方法。定義此方法是查詢特定更新的好時機,props因為它使我們有機會計算更改並更新元件的內部狀態。

這是我們可以根據新道具更新狀態的時間。

這裡要記住的一件事是,即使componentWillReceiveProps()呼叫該方法,它的值props也可能沒有改變。它總是以檢查道具值的變化是一個好主意。

例如,讓我們在活動列表中新增一個重新整理按鈕,這樣我們的使用者就可以請求重新請求github事件api。

我們將使用componentWillReceiveProps()鉤子來請求元件重新載入它的資料。由於我們的元件是有狀態的,我們將希望用新資料重新整理此狀態,因此我們不能簡單地更新props元件。我們可以使用該componentWillReceiveProps()方法告訴我們想要重新整理的元件。

讓我們在包含元素上新增一個按鈕,該按鈕傳遞一個requestRefresh布林值,告訴Content元件重新整理。

class Container extends React.Component {
  constructor(props) {
    super(props);

    this.state = {refreshing: false}
  }

  // Bound to the refresh button
  refresh() {
    this.setState({refreshing: true})
  }

  // Callback from the `Content` component
  onComponentRefresh() {
    this.setState({refreshing: false});
  }

  render() {
    const {refreshing} = this.state;
    return (
      <div className='notificationsFrame'>
        <div className='panel'>
          <Header title="Github activity" />
          {/* refreshing is the component's state */}
          <Content
            onComponentRefresh={this.onComponentRefresh.bind(this)}
            requestRefresh={refreshing}
            fetchData={fetchEvents} />
          {/* A container for styling */}
          <Footer>
            <button onClick={this.refresh.bind(this)}>
              <i className="fa fa-refresh" />
              Refresh
            </button>
          </Footer>
        </div>
      </div>
    )
  }
}

請注意,我們在這裡有一個新元素,用於顯示元素的子元素。這是一種允許我們在某些內容周圍新增CSS類的模式。

class Footer extends React.Component {
  render() {
    return (
      <div className='footer'>
        {this.props.children}
      </div>
    )
  }
}

使用這個新的proprequestRefreshprop),我們可以在更改值時更新activities我們的state物件。

class Content extends React.Component {
  // ...
  componentWillReceiveProps(nextProps) {
    // Check to see if the requestRefresh prop has changed
    if (nextProps.requestRefresh !== this.props.requestRefresh) {
      this.setState({loading: true}, this.updateData);
    }
  }
  // ...
}

 

時間

此演示使用來自JSON檔案的靜態資料,並在重新整理時隨機選取四個元素。這是為了模擬重新整理而設定的。

componentWillUnmount()

在解除安裝元件之前,React將呼叫componentWillUnmount()回撥。這是處理我們可能需要的任何清理事件的時間,例如清除超時,清除資料,斷開websockets等。

例如,我們上次使用的時鐘元件,我們設定每秒呼叫一次超時。當元件準備好解除安裝時,我們希望確保清除此超時,以便我們的JavaScript不會繼續為實際不存在的元件執行超時。

回想一下,timer我們構建的元件如下所示:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = this.getTime();
  }

  componentDidMount() {
    this.setTimer();
  }

  setTimer() {
    this.timeout = setTimeout(this.updateClock.bind(this), 1000);
  }

  updateClock() {
    this.setState(this.getTime, this.setTimer);
  }

  getTime() {
    const currentTime = new Date();
    return {
      hours: currentTime.getHours(),
      minutes: currentTime.getMinutes(),
      seconds: currentTime.getSeconds(),
      ampm: currentTime.getHours() >= 12 ? 'pm' : 'am'
    }
  }

  // ...
  render() {

  }
}

當我們的時鐘將被解除安裝時,我們將要清除我們在setTimer()元件上的函式中建立的超時。新增該componentWillUnmount()功能可以完成這種必要的清理工作。

class Clock extends React.Component {
  // ...
  componentWillUnmount() {
    if (this.timeout) {
      clearTimeout(this.timeout);
    }
  }
  // ...
}

 

12 :52:01 日下午

這些是我們可以在React框架中與之互動的一些生命週期鉤子。在構建我們的反應應用程式時,我們會使用這些,因此熟悉它們,它們存在以及如何掛鉤元件的生命是一個好主意。

我們確實在這篇文章中引入了一個新概念,我們在其中添加了一個回撥函式:我們在一個要從子程序呼叫的元件上添加了一個回撥函式。在下一節中,我們將討論如何定義和記錄prop元件的API,以便在跨團隊和應用程式共享元件時使用。

學習REACT正確的方法

React和朋友的最新,深入,完整的指南。

下載第一章

❮上一個

下一章:

包裝和PropTypes

下一個 ❯

本教程系列的完整原始碼可以在GitHub repo找到,其中包括所有樣式和程式碼示例。

如果您在任何時候感到困難,還有其他問題,請隨時通過以下方式與我們聯絡: