React生命週期原理與用法踩坑筆記
本文例項講述了React生命週期原理與用法。分享給大家供大家參考,具體如下:
React生命週期
生命週期概覽
生命週期的狀態
元件的生命週期可分成三個狀態:
- Mounting:已插入真實 DOM
- Updating:正在被重新渲
- Unmounting:已移出真實 DOM
- componentWillMount 在渲染前呼叫,在客戶端也在服務端。
生命週期介紹
componentDidMount :
在第一次渲染後呼叫,只在客戶端。之後元件已經生成了對應的DOM結構,可以通過this.getDOMNode()來進行訪問。 如果你想和其他JavaScript框架一起使用,可以在這個方法中呼叫setTimeout,setInterval或者傳送AJAX請求等操作(防止非同步操作阻塞UI)。
componentWillReceiveProps
在元件接收到一個新的 prop (更新後)時被呼叫。這個方法在初始化render時不會被呼叫。
shouldComponentUpdate
返回一個布林值。在元件接收到新的props或者state時被呼叫。在初始化時或者使用forceUpdate時不被呼叫。
可以在你確認不需要更新元件時使用。
componentWillUpdate
在元件接收到新的props或者state但還沒有render時被呼叫。在初始化時不會被呼叫。
componentDidUpdate
在元件完成更新後立即呼叫。在初始化時不會被呼叫。
componentWillUnmount
在元件從 DOM 中移除之前立刻被呼叫。
程式碼示意
class Content extends React.Component { componentWillMount() { console.log('Component WILL MOUNT!') } componentDidMount() { console.log('Component DID MOUNT!') } componentWillReceiveProps(newProps) { console.log('Component WILL RECEIVE PROPS!') } shouldComponentUpdate(newProps,newState) { return true; } componentWillUpdate(nextProps,nextState) { console.log('Component WILL UPDATE!'); } componentDidUpdate(prevProps,prevState) { console.log('Component DID UPDATE!') } componentWillUnmount() { console.log('Component WILL UNMOUNT!') }
React16.3生命週期
安裝
在建立元件的例項並將其插入DOM時,將按以下順序呼叫這些方法:
constructor()
React元件的建構函式在安裝之前被呼叫。在實現React.Component子類的建構函式時,應該super(props)在任何其他語句之前呼叫。否則,this.props將在建構函式中未定義,這可能導致錯誤。
通常,在React中,建構函式僅用於兩個目的:
通過分配物件來初始化本地狀態this.state。
將事件處理程式方法繫結到例項。
不應該打電話setState()給constructor()。相反,如果您的元件需要使用本地狀態,請直接在建構函式中指定初始狀態this.state。
建構函式是his.state直接分配的唯一位置。在所有其他方法中,需要使用this.setState()。
static getDerivedStateFromProps()
getDerivedStateFromProps在呼叫render方法之前呼叫,無論是在初始安裝還是後續更新。它應該返回一個更新狀態的物件,或者返回null以不更新任何狀態。
render()
render()方法是類元件中唯一必需的方法。
呼叫時,它應檢查this.props並this.state返回以下型別之一:
- React elements。通常通過JSX建立。
- Arrays and fragments。讓您從渲染中返回多個元素。有關更多詳細資訊,請參閱片段文件。
- Portals。
- 字串和數字。它們在DOM中呈現為文字節點。
- 布林或null。什麼都沒有。
該render()函式應該無狀態的,這意味著它不會修改元件狀態,每次呼叫時都返回相同的結果,並且它不直接與瀏覽器互動。
如果您需要與瀏覽器進行互動,請執行componentDidMount()或其他生命週期方法。保持render()純粹使元件更容易思考。
如果shouldComponentUpdate()返回false,則render()不會被呼叫
componentDidMount()
- componentDidMount()在安裝元件(插入樹中)後立即呼叫。需要DOM節點的初始化應該放在這裡。如果需要從遠端端點載入資料,這是例項化網路請求的好地方。
- 此方法是設定任何訂閱的好地方。如果您這樣做,請不要忘記取消訂閱componentWillUnmount()。
- 您可以在componentDidMount()立即使用this.setState()。它將觸發額外的渲染,但它將在瀏覽器更新螢幕之前發生。這保證即使render()在這種情況下將被呼叫兩次,使用者也不會看到中間狀態。請謹慎使用此模式,因為它通常會導致效能問題。在大多數情況下,您應該能夠分配初始狀態constructor()。但是,當您需要在渲染依賴於其大小或位置的東西之前測量DOM節點時,可能需要對模態和工具提示等情況進行處理。
這些方法被認為是遺留的,應該在新程式碼中避免它們:
UNSAFE_componentWillMount()
更新
props or state 的更改可能導致更新。重新渲染元件時,將按以下順序呼叫這些方法:
static getDerivedStateFromProps()
render()
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps,prevState)
getSnapshotBeforeUpdate()在最近呈現的輸出被提交到例如DOM之前呼叫。它使得元件可以在可能更改之前從DOM捕獲一些資訊(例如滾動位置)。此生命週期返回的任何值都將作為引數傳遞給componentDidUpdate()。
此用例並不常見,但它可能出現在需要以特殊方式處理滾動位置的聊天執行緒等UI中。
官網的例子
class ScrollingList extends React.Component { constructor(props) { super(props); this.listRef = React.createRef(); } getSnapshotBeforeUpdate(prevProps,prevState) { // Are we adding new items to the list? // Capture the scroll position so we can adjust scroll later. if (prevProps.list.length < this.props.list.length) { const list = this.listRef.current; return list.scrollHeight - list.scrollTop; } return null; } componentDidUpdate(prevProps,prevState,snapshot) { // If we have a snapshot value,we've just added new items. // Adjust scroll so these new items don't push the old ones out of view. // (snapshot here is the value returned from getSnapshotBeforeUpdate) if (snapshot !== null) { const list = this.listRef.current; list.scrollTop = list.scrollHeight - snapshot; } } render() { return ( <div ref={this.listRef}>{/* ...contents... */}</div> ); } }
componentDidUpdate()
componentDidUpdate()更新發生後立即呼叫。初始渲染不會呼叫此方法。
將此作為在更新元件時對DOM進行操作的機會。只要您將當前道具與之前的道具進行比較(例如,如果道具未更改,則可能不需要網路請求),這也是進行網路請求的好地方。
componentDidUpdate(prevProps) { // Typical usage (don't forget to compare props): if (this.props.userID !== prevProps.userID) { this.fetchData(this.props.userID); } }
componentDidUpdate()但要注意,必須在一個條件下被包裹就像上面的例子中,否則會導致無限迴圈。它還會導致額外的重新渲染,雖然使用者不可見,但會影響元件效能。
componentDidUpdate():如果shouldComponentUpdate()返回false,則不會被呼叫。
這些方法被認為是遺留的,您應該在新程式碼中避免它們:
UNSAFE_componentWillUpdate()
UNSAFE_componentWillReceiveProps()
解除安裝
從DOM中刪除元件時呼叫此方法:
componentWillUnmount()
componentWillUnmount()在解除安裝和銷燬元件之前立即呼叫。在此方法中執行任何必要的清理,例如使計時器無效,取消網路請求或清除在其中建立的任何訂閱componentDidMount()。
不應該呼叫setState(),componentWillUnmount()因為元件永遠不會被重新呈現。解除安裝元件例項後,將永遠不會再次安裝它。
錯誤處理
在渲染期間,生命週期方法或任何子元件的建構函式中發生錯誤時,將呼叫這些方法。
static getDerivedStateFromError()
static getDerivedStateFromError(error)
在後代元件丟擲錯誤後呼叫此生命週期。它接收作為引數丟擲的錯誤,並應返回值以更新狀態。
componentDidCatch()
componentDidCatch(error,info)
在後代元件丟擲錯誤後呼叫此生命週期。它接收兩個引數:
error - 丟擲的錯誤。
info- componentStack包含鍵的物件,其中包含有關哪個元件引發錯誤的資訊。
如果發生錯誤,可以componentDidCatch()通過呼叫呈現回退UI setState,但在將來的版本中將不推薦使用。使用static getDerivedStateFromError()處理回退,而不是渲染。
componentDidCatch()在“提交”階段被呼叫,因此允許副作用。它應該用於記錄錯誤之類的事情:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error,info) { // Example "componentStack": // in ComponentThatThrows (created by App) // in ErrorBoundary (created by App) // in div (created by App) // in App logComponentStackToMyService(info.componentStack); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; } return this.props.children; } }
希望本文所述對大家react程式設計有所幫助。