React生命週期-踩坑記_10

React生命週期

生命週期概覽

生命週期的狀態

組件的生命週期可分紅三個狀態:html

  • Mounting:已插入真實 DOM
  • Updating:正在被從新渲
  • Unmounting:已移出真實 DOM
  • componentWillMount 在渲染前調用,在客戶端也在服務端。

生命週期介紹

componentDidMount :

在第一次渲染後調用,只在客戶端。以後組件已經生成了對應的DOM結構,能夠經過this.getDOMNode()來進行訪問。 若是你想和其餘JavaScript框架一塊兒使用,能夠在這個方法中調用setTimeout, setInterval或者發送AJAX請求等操做(防止異步操做阻塞UI)。react

componentWillReceiveProps

在組件接收到一個新的 prop (更新後)時被調用。這個方法在初始化render時不會被調用。瀏覽器

shouldComponentUpdate

返回一個布爾值。在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
能夠在你確認不須要更新組件時使用。網絡

componentWillUpdate

在組件接收到新的props或者state但尚未render時被調用。在初始化時不會被調用。框架

componentDidUpdate

在組件完成更新後當即調用。在初始化時不會被調用。異步

componentWillUnmount

在組件從 DOM 中移除以前馬上被調用。async

代碼示意

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; 
  }
}

image

image

http://projects.wojtekmaj.pl/...

https://reactjs.org/blog/2018...

https://reactjs.org/docs/reac...

相關文章
相關標籤/搜索