30天入坑React ---------------day07 Lifecycle Hooks
這篇文章是30天React系列的一部分 。
在本系列中,我們將從非常基礎開始,逐步瞭解您需要了解的所有內容,以便開始使用React。如果您曾經想學習React,那麼這裡就是您的最佳選擇!
生命週期鉤子
今天,我們將介紹一些我們可以與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>
)
}
}
<Footer />
請注意,我們在這裡有一個新元素,用於顯示元素的子元素。這是一種允許我們在某些內容周圍新增CSS類的模式。
class Footer extends React.Component { render() { return ( <div className='footer'> {this.props.children} </div> ) } }
使用這個新的prop
(requestRefresh
prop),我們可以在更改值時更新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上找到,其中包括所有樣式和程式碼示例。
如果您在任何時候感到困難,還有其他問題,請隨時通過以下方式與我們聯絡:
- 在文章末尾評論這篇文章
- 通過[email protected]傳送電子郵件給我們
- 加入我們的gitter室
- 傳送電子郵件至@fullstackreact