反應生命週期的圓
React組件在其應用生命週期中會經歷不同的階段,儘管幕後發生的事情可能並不明顯。
這些階段包括:
- 掛載
- 更新
- 解除安裝
- 錯誤處理
每個階段都有相應的方法,可以在該階段對組件執行特定操作。例如,當從網絡獲取數據時,您可能希望在componentDidMount()
方法(在掛載階段可用)中調用處理API調用的函數。
了解不同的生命週期方法對於React應用程序的開發至關重要,因為它允許我們在需要時精確地觸發操作,而不會與其他操作混淆。本文將介紹每個生命週期,包括可用的方法以及我們使用它們的場景類型。
掛載階段
將掛載視為組件生命週期的初始階段。在掛載發生之前,組件尚未存在——它只是DOM中的一閃而過,直到掛載發生並將其作為文檔的一部分連接起來。
一旦組件掛載,我們就可以利用許多方法: constructor()
、 render()
、 componentDidMount()
和static getDerivedStateFromProps()
。每個方法都有其自身的用途,讓我們按順序來看一下。
constructor()
當直接在組件上設置狀態以將方法綁定在一起時,需要constructor()
方法。它看起來像這樣:
// 一旦輸入組件開始掛載... constructor(props) { // ...設置一些props... super(props); // ...在這種情況下,是一個空白用戶名... this.state = { username: '' }; // ...然後綁定一個處理輸入更改的方法this.handleInputChange = this.handleInputChange.bind(this); }
重要的是要知道, constructor
是創建組件時調用的第一個方法。組件尚未渲染(即將到來),但DOM已經知道它,我們可以在它渲染之前與它掛鉤。因此,這不是我們調用setState()
或引入任何副作用的地方,因為組件仍然處於構建階段!
我之前寫過一篇關於refs的教程,我注意到的一件事是在使用React.createRef()
時,可以在constructor
中設置ref。這是合理的,因為refs用於更改值而無需props或必須使用更新值重新渲染組件:
constructor(props) { super(props); this.state = { username: '' }; this.inputText = React.createRef(); }
render()
render()
方法是組件的標記在前端顯示的地方。用戶此時可以看到並訪問它。如果您曾經創建過React組件,那麼您已經熟悉它了——即使您沒有意識到——因為它需要輸出標記。
class App extends React.Component { // 掛載過程中,請渲染以下內容! render() { return ( <div> <p>Hello World!</p> </div> ) } }
但這並不是render()
的全部用途!它還可以用於渲染組件數組:
class App extends React.Component { render () { return [ <h2 id="JavaScript-Tools">JavaScript Tools</h2> , <frontend></frontend>, <backend></backend> ] } }
甚至組件片段:
class App extends React.Component { render() { return ( <react.fragment><p>Hello World!</p></react.fragment> ) } }
我們還可以使用它來渲染DOM層次結構之外的組件(類似於React Portal):
// 我們正在創建一個門戶,允許組件在DOM中移動class Portal extends React.Component { // 首先,我們創建一個div元素constructor() { super(); this.el = document.createElement("div"); } // 掛載後,讓我們追加組件的子元素componentDidMount = () => { portalRoot.appendChild(this.el); }; // 如果組件從DOM中移除,那麼我們也將其子元素移除componentWillUnmount = () => { portalRoot.removeChild(this.el); }; // 啊,現在我們可以根據需要渲染組件及其子元素render() { const { children } = this.props; return ReactDOM.createPortal(children, this.el); } }
當然, render()
可以渲染數字和字符串……
class App extends React.Component { render () { return "Hello World!" } }
以及null或布爾值:
class App extends React.Component { render () { return null } }
componentDidMount()
componentDidMount()
這個名字是否說明了它的含義?此方法在組件掛載(即連接到DOM)後調用。在我撰寫的另一篇關於在React中獲取數據的教程中,這就是您要向API發出請求以獲取數據的地方。
我們可以使用您的fetch方法:
fetchUsers() { fetch(`https://jsonplaceholder.typicode.com/users`) .then(response => response.json()) .then(data => this.setState({ users: data, isLoading: false, }) ) .catch(error => this.setState({ error, isLoading: false })); }
然後在componentDidMount()
鉤子中調用該方法:
componentDidMount() { this.fetchUsers(); }
我們還可以添加事件監聽器:
componentDidMount() { el.addEventListener() }
很簡潔,對吧?
static getDerivedStateFromProps()
這是一個有點冗長的名字,但static getDerivedStateFromProps()
並不像聽起來那麼複雜。它在掛載階段的render()
方法之前以及更新階段之前調用。它返回一個對象來更新組件的狀態,或者在沒有要更新的內容時返回null
。
為了理解它的工作原理,讓我們實現一個計數器組件,它將為其計數器狀態設置一個特定值。只有當maxCount
的值更高時,此狀態才會更新。 maxCount
將從父組件傳遞。
這是父組件:
class App extends React.Component { constructor(props) { super(props) this.textInput = React.createRef(); this.state = { value: 0 } } handleIncrement = e => { e.preventDefault(); this.setState({ value: this.state.value 1 }) }; handleDecrement = e => { e.preventDefault(); this.setState({ value: this.state.value - 1 }) }; render() { return ( <react.fragment><p>Max count: { this.state.value }</p> - <counter maxcount="{this.state.value}"></counter></react.fragment> ) } }
我們有一個按鈕用於增加maxCount
的值,我們將其傳遞給Counter
組件。
class Counter extends React.Component { state={ counter: 5 } static getDerivedStateFromProps(nextProps, prevState) { if (prevState.counter <p>Count: {this.state.counter}</p> ) } }
在Counter
組件中,我們檢查counter
是否小於maxCount
。如果是,我們將counter
設置為maxCount
的值。否則,我們什麼也不做。
更新階段
當組件的props或狀態更改時,會發生更新階段。與掛載一樣,更新也有自己的一組可用方法,我們接下來將介紹。也就是說,值得注意的是, render()
和getDerivedStateFromProps()
也會在此階段觸發。
shouldComponentUpdate()
當組件的狀態或props更改時,我們可以使用shouldComponentUpdate()
方法來控制組件是否應該更新。此方法在渲染髮生之前以及接收狀態和props時調用。默認行為為true
。要每次狀態或props更改時都重新渲染,我們會這樣做:
shouldComponentUpdate(nextProps, nextState) { return this.state.value !== nextState.value; }
當返回false
時,組件不會更新,而是調用render()
方法來顯示組件。
getSnapshotBeforeUpdate()
我們可以做的一件事是在某個時間點捕獲組件的狀態,這就是getSnapshotBeforeUpdate()
的設計目的。它在render()
之後但提交任何新更改到DOM之前調用。返回值作為第三個參數傳遞給componentDidUpdate()
。
它將先前狀態和props作為參數:
getSnapshotBeforeUpdate(prevProps, prevState) { // ... }
在我看來,此方法的用例很少。它是一種您可能不會經常使用到的生命週期方法。
componentDidUpdate()
將componentDidUpdate()
添加到方法列表中,其中名稱大致說明了所有內容。如果組件更新,那麼我們可以使用此方法在此時與它掛鉤,並將其傳遞給組件的先前props和狀態。
componentDidUpdate(prevProps, prevState) { if (prevState.counter !== this.state.counter) { // ... } }
如果您曾經使用過getSnapshotBeforeUpdate()
,您還可以將返回值作為參數傳遞給componentDidUpdate()
:
componentDidUpdate(prevProps, prevState, snapshot) { if (prevState.counter !== this.state.counter) { // .... } }
卸載階段
我們在這裡幾乎看到了掛載階段的反面。正如您可能預期的那樣,卸載發生在組件從DOM中清除並且不再可用時。
我們這裡只有一個方法: componentWillUnmount()
這在組件卸載和銷毀之前調用。這就是我們想要在組件離開後執行任何必要的清理的地方,例如刪除可能在componentDidMount()
中添加的事件監聽器,或清除訂閱。
// 刪除事件監聽器componentWillUnmount() { el.removeEventListener() }
錯誤處理階段
組件中可能會出現問題,這可能會導致錯誤。我們已經有一段時間使用錯誤邊界來幫助解決這個問題。此錯誤邊界組件使用一些方法來幫助我們處理可能遇到的錯誤。
getDerivedStateFromError()
我們使用getDerivedStateFromError()
來捕獲從子組件拋出的任何錯誤,然後我們使用它來更新組件的狀態。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return ( <h1 id="Oops-something-went-wrong">Oops, something went wrong :(</h1> ); } return this.props.children; } }
在此示例中,當從子組件拋出錯誤時, ErrorBoundary
組件將顯示“哎呀,出現了一些問題”。
componentDidCatch()
雖然getDerivedStateFromError()
適用於在發生副作用(如錯誤日誌記錄)的情況下更新組件的狀態,但我們應該使用componentDidCatch()
,因為它在提交階段調用,此時DOM已更新。
componentDidCatch(error, info) { // 將錯誤記錄到服務}
getDerivedStateFromError()
和componentDidCatch()
都可以在ErrorBoundary
組件中使用:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { // 將錯誤記錄到服務} render() { if (this.state.hasError) { return ( <h1 id="Oops-something-went-wrong">Oops, something went wrong :(</h1> ); } return this.props.children; } }
這就是React組件的生命週期!
了解React組件如何與DOM交互是一件很酷的事情。很容易認為會發生一些“魔法”,然後頁面上就會出現一些東西。但是React組件的生命週期表明,這種瘋狂是有秩序的,它旨在賦予我們很大的控制權,以便從組件到達DOM到它消失的時間發生的事情。
我們在相對較短的空間內涵蓋了很多內容,但希望這能讓您很好地了解React如何處理組件,以及我們在處理的各個階段擁有什麼樣的能力。如果您對這裡介紹的任何內容不清楚,請隨時提出任何問題,我很樂意盡力提供幫助!
以上是反應生命週期的圓的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)