組件的生命周期
React中組件也有生命周期,也就是說也有很多鈎子函數供我們使用, 組件的生命周期,我們會分為四個階段,初始化、運行中、銷毀、錯誤處理(16.3之后)
初始化
在組件初始化階段會執行
- constructor
- static getDerivedStateFromProps()
- componentWillMount() / UNSAFE_componentWillMount()
- render()
- componentDidMount()
更新階段
props
或state
的改變可能會引起組件的更新,組件重新渲染的過程中會調用以下方法:
- componentWillReceiveProps() / UNSAFE_componentWillReceiveProps()
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- componentWillUpdate() / UNSAFE_componentWillUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
卸載階段
- componentWillUnmount()
錯誤處理
- componentDidCatch()
各生命周期詳解
1.constructor(props)
React組件的構造函數在掛載之前被調用。在實現React.Component
構造函數時,需要先在添加其他內容前,調用super(props)
,用來將父組件傳來的props
綁定到這個類中,使用this.props
將會得到。
官方建議不要在constructor
引入任何具有副作用和訂閱功能的代碼,這些應當使用componentDidMount()
。
constructor
中應當做些初始化的動作,如:初始化state
,將事件處理函數綁定到類實例上,但也不要使用setState()
。如果沒有必要初始化state或綁定方法,則不需要構造constructor
,或者把這個組件換成純函數寫法。
當然也可以利用props
初始化state
,在之后修改state
不會對props
造成任何修改,但仍然建議大家提升狀態到父組件中,或使用redux
統一進行狀態管理。
constructor(props) { super(props); this.state = { isLiked: props.isLiked }; }
2.static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps
是react16.3之后新增,在組件實例化后,和接受新的props
后被調用。他必須返回一個對象來更新狀態,或者返回null表示新的props不需要任何state的更新。
如果是由於父組件的props
更改,所帶來的重新渲染,也會觸發此方法。
調用steState()
不會觸發getDerivedStateFromProps()
。
之前這里都是使用constructor
+componentWillRecieveProps
完成相同的功能的
3. componentWillMount() / UNSAFE_componentWillMount()
componentWillMount()
將在React未來版本(官方說法 17.0)中被棄用。UNSAFE_componentWillMount()
在組件掛載前被調用,在這個方法中調用setState()
不會起作用,是由於他在render()
前被調用。
為了避免副作用和其他的訂閱,官方都建議使用componentDidMount()
代替。這個方法是用於在服務器渲染上的唯一方法。這個方法因為是在渲染之前被調用,也是惟一一個可以直接同步修改state的地方。
4.render()
render()方法是必需的。當他被調用時,他將計算this.props
和this.state
,並返回以下一種類型:
- React元素。通過jsx創建,既可以是dom元素,也可以是用戶自定義的組件。
- 字符串或數字。他們將會以文本節點形式渲染到dom中。
- Portals。react 16版本中提出的新的解決方案,可以使組件脫離父組件層級直接掛載在DOM樹的任何位置。
- null,什么也不渲染
- 布爾值。也是什么都不渲染。
當返回null
,false
,ReactDOM.findDOMNode(this)
將會返回null,什么都不會渲染。
render()
方法必須是一個純函數,他不應該改變state
,也不能直接和瀏覽器進行交互,應該將事件放在其他生命周期函數中。 如果shouldComponentUpdate()
返回false
,render()
不會被調用。
5. componentDidMount
componentDidMount
在組件被裝配后立即調用。初始化使得DOM節點應該進行到這里。
通常在這里進行ajax請求
如果要初始化第三方的dom庫,也在這里進行初始化。只有到這里才能獲取到真實的dom.
6.componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)
官方建議使用getDerivedStateFromProps
函數代替componentWillReceiveProps
。當組件掛載后,接收到新的props
后會被調用。如果需要更新state
來響應props
的更改,則可以進行this.props
和nextProps
的比較,並在此方法中使用this.setState()
。
如果父組件會讓這個組件重新渲染,即使props
沒有改變,也會調用這個方法。
React不會在組件初始化props時調用這個方法。調用this.setState
也不會觸發。
7.shouldComponentUpdate(nextProps, nextState)
調用shouldComponentUpdate
使React知道,組件的輸出是否受state
和props
的影響。默認每個狀態的更改都會重新渲染,大多數情況下應該保持這個默認行為。
在渲染新的props
或state
前,shouldComponentUpdate
會被調用。默認為true
。這個方法不會在初始化時被調用,也不會在forceUpdate()
時被調用。返回false
不會阻止子組件在state
更改時重新渲染。
如果shouldComponentUpdate()
返回false
,componentWillUpdate
,render
和componentDidUpdate
不會被調用。
官方並不建議在shouldComponentUpdate()
中進行深度查詢或使用JSON.stringify()
,他效率非常低,並且損傷性能。
8.UNSAFE_componentWillUpdate(nextProps, nextState)
在渲染新的state
或props
時,UNSAFE_componentWillUpdate
會被調用,將此作為在更新發生之前進行准備的機會。這個方法不會在初始化時被調用。
不能在這里使用this.setState(),也不能做會觸發視圖更新的操作。如果需要更新state
或props
,調用getDerivedStateFromProps
。
9.getSnapshotBeforeUpdate()
在react render()
后的輸出被渲染到DOM之前被調用。它使您的組件能夠在它們被潛在更改之前捕獲當前值(如滾動位置)。這個生命周期返回的任何值都將作為參數傳遞給componentDidUpdate()。
10.componentDidUpdate(prevProps, prevState, snapshot)
在更新發生后立即調用componentDidUpdate()
。此方法不用於初始渲染。當組件更新時,將此作為一個機會來操作DOM。只要您將當前的props與以前的props進行比較(例如,如果props沒有改變,則可能不需要網絡請求),這也是做網絡請求的好地方。
如果組件實現getSnapshotBeforeUpdate()
生命周期,則它返回的值將作為第三個“快照”參數傳遞給componentDidUpdate()
。否則,這個參數是undefined
。
11.componentWillUnmount()
在組件被卸載並銷毀之前立即被調用。在此方法中執行任何必要的清理,例如使定時器無效,取消網絡請求或清理在componentDidMount
中創建的任何監聽。
12.componentDidCatch(error, info)
錯誤邊界是React組件,可以在其子組件樹中的任何位置捕獲JavaScript錯誤,記錄這些錯誤並顯示回退UI,而不是崩潰的組件樹。錯誤邊界在渲染期間,生命周期方法以及整個樹下的構造函數中捕獲錯誤。
如果類組件定義了此生命周期方法,則它將成錯誤邊界。在它中調用setState()
可以讓你在下面的樹中捕獲未處理的JavaScript錯誤,並顯示一個后備UI。只能使用錯誤邊界從意外異常中恢復; 不要試圖將它們用於控制流程。
錯誤邊界只會捕獲樹中下面組件中的錯誤。錯誤邊界本身不能捕獲錯誤。
PureComponent
PureComponnet
里如果接收到的新屬性或者是更改后的狀態和原屬性、原狀態相同的話,就不會去重新render了 在里面也可以使用shouldComponentUpdate
,而且。是否重新渲染以shouldComponentUpdate
的返回值為最終的決定因素。
import React, { PureComponent } from 'react'
class YourComponent extends PureComponent {
……
}
ref
React提供的這個ref
屬性,表示為對組件真正實例的引用,其實就是ReactDOM.render()
返回的組件實例,ref
可以掛載到組件上也可以是dom元素上。
- 掛到組件(
class
聲明的組件)上的ref表示對組件實例的引用。不能在函數式組件上使用 ref 屬性,因為它們沒有實例: - 掛載到dom元素上時表示具體的dom元素節點。
在React 最新的版本中,要使用ref
, 需要使用React.createRef
方法先生成一個ref
。
import React, { Component, createRef } from 'react' import ReactDOM from 'react-dom' class App extends Component { constructor() { super() // 創建inputRef this.inputRef=createRef() } componentDidMount () { console.log(this.inputRef.current) // <input type="text"> } render () { return ( <div> {/* 關聯ref和dom */} <input type="text" ref={this.inputRef} /> </div> ) } } ReactDOM.render( <App/>, document.getElementById('root') )
React Hooks
React Hooks 是 React 16.7.0-alpha
版本推出的新特性, 有了React Hooks,在 react 函數組件中,也可以使用類組件(classes components)的 state 和 組件生命周期。通過下面幾個例子來學習React Hooks。
- State Hook
// useState是react包提供的一個方法 import React, { useState } from "react"; import ReactDOM from "react-dom"; const Counter = () => { // useState 這個方法可以為我們的函數組件擁有自己的state,它接收一個用於初始 state 的值,返回一對變量。這里我們把計數器的初始值設置為0, 方法都是以set開始 const [count, setCount] = useState(0); return ( <div> <p>你點擊了{count}次</p> <button onClick={() => setCount(count + 1)}>點擊</button> </div> ); }; const rootElement = document.getElementById("root"); ReactDOM.render(<Counter />, rootElement);
- Effect Hook
// useState是react包提供的一個方法 import React, { useState, useEffect } from "react"; import ReactDOM from "react-dom"; const Counter = () => { // useState 這個方法可以為我們的函數組件擁有自己的state,它接收一個用於初始 state 的值,返回一對變量。這里我們把計數器的初始值設置為0, 方法都是以set開始 const [count, setCount] = useState(0); // 類似於componentDidMount或者componentDidUpdate: useEffect(() => { // 更改網頁的標題,還可以做其它的監聽 document.title = `你點擊了${count}次`; }); return ( <div> <p>你點擊了{count}次</p> <button onClick={() => setCount(count + 1)}>點擊</button> </div> ); }; const rootElement = document.getElementById("root"); ReactDOM.render(<Counter />, rootElement);
- React Hooks 的規則
- 只能在頂層調用Hooks。不要在循環,條件或嵌套函數中調用Hook。
- 不要從常規JavaScript函數中調用Hook。只在React函數式組件調用Hooks。
- 自定義hooks可以選擇講解
- react 內置hooks api
原文鏈接:https://zhuanlan.zhihu.com/p/129012484