React(v16.8.4)生命周期詳解

来源:https://www.cnblogs.com/hezhi/archive/2019/03/17/10547186.html
-Advertisement-
Play Games

當前版本v16.8.4 裝載過程(組件第一次在DOM樹中渲染的過程): constructor(常用) getInitialState(v16.0已廢棄) getDefaultProps(v16.0已廢棄) componentWillMount(v17.0中將被棄用) getDerivedState ...


當前版本v16.8.4

裝載過程(組件第一次在DOM樹中渲染的過程):

constructor(常用) -> getInitialState(v16.0已廢棄) -> getDefaultProps(v16.0已廢棄) -> componentWillMount(v17.0中將被棄用) -> getDerivedStateFromProps(v16.3新增,併在v16.4中升級優化了一下) -> render(必須要) -> componentDidMount(常用)

更新過程(當組件被重新渲染的過程,state改變或props改變或父組件forceUpdate引發子組件的重新渲染):

componentWillReceiveProps(v17.0中將被棄用) -> getDerivedStateFromProps -> shouldComponentUpdate -> componentWillUpdate(v17.0中將被棄用) -> render -> getSnapshotBeforeUpdate -> componentDidUpdate

卸載過程(組件從DOM中刪除的過程):

componentWillUnmount

錯誤處理(當組件發生錯誤的時候,用得極少)

getDerivedStateFromError(v16.6新增) -> componentDidCatch(未來將被廢棄)

constructor:(可以不寫,直接寫state = {})

ES6中每個類的構造函數,並不是每個組件都需要定義自己的構造函數。比如無狀態組件。
作用:

  1. 初始化state, 例如super(props)下的 this.state = {}
  2. 綁定成員函數的this環境。例如 this.onClickButton = this.onClickButton.bind(this)。但這種方案一般都會用箭頭函數代替
    而綜合以上兩點作用,其實很多時候,你會在antd官網的例子上看到一些例子,並沒有使用contructor, 而是直接簡寫為
  state = {
   count: 0
  }
  // 這是因為在ES6的繼承中,其實不管子類寫不寫constructor,在new實例的過程都會給補上constructor
  class ColorPoint extends Point {
  
  }
  // 等同於 
  class ColorPoint extends Point {
    constructor(...args) {
      super(...args);
    }
  }

getInitialState: (隨著v16.0版本createClass被棄用,該方法也不存在了)

返回值會用來初始化組件的this.state

getDefaultProps: (隨著v16.0版本createClass被棄用,該方法也不存在了)

返回值可以作為props的初始值

componentWillMount:(即將在v17.0中被棄用,不用)

可以做:

  1. 直接使用setState改變組件狀態,render會列印一次改變後的值(但是你這樣做沒什麼意義,還不如直接在constructor的時候設好初始值)
  2. 發送Ajax請求(服務端渲染的時候)

不要做:

  1. 發送ajax請求(原因如下)
  2. 執行DOM操作(這個階段DOM還沒渲染出來)

最終建議:

不要用這個生命周期

在沒被棄用的時候也幾乎不用,這時候沒有任何渲染出來的結果,即使調用this.setState修改狀態也不會引發重新繪製。所有在這裡可以做的事,都可以提前到 constructor中去做。有些人可能用過vue, 在vue中也經常在created中去請求介面,比如可能初始值是0,然後在created中請求介面,簡單的理解成想頁面在展示的時候就直接顯示介面請求返回後的數據1了,而不是我們看到頁面的時候先看到0,然後突然變成1了。個人理解vue的created和react的componentWillMount應該也是相差不了太多的,如果是在componentWillMount的時候你的數據還不是1的話,你這時候請求數據,其實是另外開了一個線程去執行非同步操作了,render函數並不會等你非同步請求結果返回1才去執行render。網路差的話,你先看到0再看到突然變成1也是很正常的事。在這裡請求和在componentDidMount中請求並不會有太大的差別。同理,其實vue中特意區分該在created中還是mounted中請求介面也是沒必要的,還不如統一到mounted/componentDidMount中去請求介面,因為我們有些方法還是要等真實dom存在後才去執行的。

getDerivedStateFromProps(props, state):

第一次在裝載階段(當前組件實例化)會被觸發比較好理解,但是組件更新階段,究竟組件更新階段的什麼操作會觸發這個函數?
假如我在父組件改變了props 會觸發這個函數嗎?答案是會。
假如我在當前組件 this.setState 會觸發這個函數嗎?在v16.3中不會,但是在v16.4以上就會了。截至2019-03-17,在 https://react.docschina.org/docs/react-component.html#static-getderivedstatefromprops 上看到的翻譯還是錯的。不信可以自己試試?
假如我在父組件只是執行了 forceUpdate 強行引發一次重新繪製,那當前組件(子組件)的getDerivedStateFromProps又會被觸發嗎?
一樣,在v16.3中不會,但是在v16.4以上就會了。
它返回一個對象來更新狀態,如果返回的是null就表示不更新任何內容
這個方法react官方都意識到很多人對如何使用它存在許多誤解(https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html),
目前很多人的博客其實寫得也有點問題的。

render:(必須要)

返回一個JSX表示的對象,然後由React庫來根據返回對象決定如何渲染。並不是返回的真實DOM,其他的生命周期都可以省,但是這個必須要

componentDidMount:(常用)

可以做:

  1. 發送ajax請求

不要做:

  1. 直接使用this.setState更新狀態,這樣會二次渲染(不過經常會有發送請求後,在回調函數里setState,這也是不可避免的)

僅在瀏覽器端執行,此時已經有了真實的dom節點,在這個階段常用於處理介面請求,或者一些DOM操作。因為有些組件的啟動動作是依賴DOM的,例如動畫等。

需要註意的是:可以在這裡發送非同步請求,在回調函數里調用setState設置state。但是儘量不要在這裡直接調用setState()設置狀態。因為會觸發一次額外的重新渲染,可能造成性能問題。

componentWillReceiveProps(nextProps):(即將在v17.0中被棄用,不用)

可以做:

  1. 根據props的更新同步組件狀態。

不要做:

  1. 發送ajax請求
  2. 尤其是不要在這裡setState

當前組件setState()不會調用;
父組件props改變會調用;
父組件通過forceUpdate重新執行render,也會調用當前組件的componentWillReceiveProps;
只要父組件的render函數被調用,那麼當前組件(子組件)都會觸發這個函數,不管父組件的props發不發生變化。例如父組件執行了 forceUpdate 強行引發一次重新繪製。當前組件的componentWillReceiveProps就會被觸發。而在當前組件this.setState是不會觸發這個函數的。因為componentWillReceiveProps適合根據新的props值(也就是參數nextProps)來計算出是不是要更新內部狀態state。更新組件內部狀態的方法就是this.setState。如果this.setState的調用導致componentWillReceiveProps再依次被調用,那就是一個死迴圈了。

componentWillReceiveProps(nextProps) {
    if (this.props.oneProp !== nextProps.oneProp) {
        // 很多人會在這裡同時寫setState 並且 發送非同步請求,其實這是不合理的
        // 應該只在這裡根據props的改變去執行 setState來同步props到組件的狀態中, 不該在這裡發送非同步請求
    }
}
// 現如今更好的方式是使用getDerivedStateFromProps 去改變state 和 componentDidUpdate 去非同步請求 來代替上面的方案

shouldComponentUpdate(nextProps, nextState):(如果你對性能有更極致的要求,水平沒達到一定高度就不要去動它了)

當前組件setState()會調用;
父組件props改變會調用;
父組件通過forceUpdate重新執行render,不會調用當前組件的shouldComponentUpdate;
這個方法主要是為了性能優化而設計的,考慮使用內置的PureComponent,而不是自己在這個函數里寫比較,更不建議在這個組件里使用JSON.stringify去深度檢查,效率非常低。
這裡返回一個布爾值,預設都返回的true, 如果返回false,那這個生命周期後面的更新階段的生命周期都不會執行了。

componentWillUpdate(nextProps, nextState):(即將在v17.0中被棄用,不用)

它可以做的,不要做的同componentWillMount一樣

當前組件setState()會調用;
父組件props改變會調用;
父組件通過forceUpdate重新執行render,也會調用當前組件的shouldComponentUpdate;
其實和componentWillMount類似,
這個方法也應該儘量避免使用,將要被遺棄。幾乎用不上。應該都統一到componentDidUpdate中去處理。

getSnapshotBeforeUpdate(prevProps, prevState):

setState(),props發生改變,父組件重新render都會調用。發生在更新狀態的render之後,這時候已經可以讀取dom了。通常用於處理滾動位置的聊天線程等UI中。
和getDerivedStateFromProps一樣它返回一個對象來更新狀態,如果返回的是null就表示不更新任何內容

componentDidUpdate(prevProps, prevState):

它可以做的,不要做的同componentDidUpdate一樣

setState(),props發生改變,父組件重新render都會調用。這個方法相對用得也比較多。同componentDidMount處理事件函數類似,如果組件被更新的時候,原有的內容被重新繪製後可能也需要再次處理事件函數。

componentDidUpdate(prevProps, prevState) {
  if(prevProps.oneProp !== this.props.oneProp) {
    // 如果有變化,在這裡做一些非同步請求,可能會在非同步請求的回調函數里setState
    // 不要直接去執行this.setState
  }
}

componentWillUnmount():

當react組件要從dom樹上刪除掉的時候,這個方法就會被調用。
如果在componentDidMount中使用非React的方法創造了一些DOM元素,如果撒手不管可能會造成記憶體泄漏,那就需要在componentWillUnmount中把這些創造的DOM元素清理掉。
應用場景:清理定時器,關閉socket, 清除監聽器等

import React, { Component } from "react";

export default class LifeCycle extends Component {
  state = {
  
  }
  static getDerivedStateFromProps(props, state) {
  
  }  
  componentDidMount = () => {

  }  
  shouldComponentUpdate = (nextProps, nextState) => {

  }
  getSnapshotBeforeUpdate = (prevProps, prevState) => {

  }
  componentDidUpdate = (prevProps, prevState) => {
    
  }
  componentWillUnmount = () => {
    
  }
  render() {
    return (
      <div>
        
      </div>
    )
  }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近我在瀏覽別的博客的文章時,無意間發現了一個很好看的小裝飾。那就是在WordPress菜單欄上的小圖標。於是我研究了研究,弄到了設置方法之後決定把它分享出來。 菜單欄的小圖標 設置步驟: 1, 我們先到WordPress後臺--插件--安裝插件頁面 搜索:Font Awesome 4 Menus, ...
  • mysql數據讀庫的\r\n換行符處理 這個問題是我在採集數據時發現的,採集網頁的數據,大概有6千多條,採集的內容保留了最原始的\r\n和\n換行字元,但在mysql管理工具中(phpmyadmin和Navicat)查看時,欄位內容有換行,不顯示\r\n和\n。 在html中展現的時候,卻不像mys ...
  • boostrap中模態框顯示在陰影之下 出現這種情況的原因我開始也搞了很久,問題出現在哪裡呢? 有事問百度,在百度上查了一下資料,他們主要的解決辦法:是 修改標簽的z-index屬性的值, 我試著改了z-index的值(z-index屬性要在設置了定位時才能用), 但是沒有解決這個問題, 後來又仔細 ...
  • 本篇文章是接著Spring Boot 入門(五):集成 AOP 進行日誌管理寫的,主要集成了樹形圖,在部門列表或者許可權列表中,樹形圖經常被用上。主要是根據相應的 API 憑藉 html 字元串 1.treetable 1 <link href="/plugins/treeTable/themes/d ...
  • 本文旨在介紹移動端h5分頁查詢實現 1.前端html 前端基於weui 樣式庫實現 參考http://jqweui.com/ 1 <div class="weui-search-bar" id="searchBar"> 2 <form class="weui-search-bar__form"> 3 ...
  • 父組件向子組件傳值 1. 組件實例定義方式,註意:一定要使用 屬性來定義父組件傳遞過來的數據 2. 使用 或簡化指令,將數據傳遞到子組件中: 子組件向父組件傳值 1. 原理:父組件將方法的引用,傳遞到子組件內部,子組件在內部調用父組件傳遞過來的方法,同時把要發送給父組件的數據,在調用方法的時候當作參 ...
  • vue+element 文件操作 作者:一粒塵土 時間:2019 3 17 註:以下操作針對 vue cli 目錄 "使用" "組件常用參數" "組件常用方法" "上傳文件" "上傳文件格式限制" "回顯文件" "下載文件" "刪除文件" 使用 使用npm安裝Element ui 依賴 配置vue中 ...
  • 參考鏈接: http://www.w3school.com.cn/xmldom/met_document_createelement.asp(createElement() 方法) http://www.w3school.com.cn/jsref/prop_option_index.asp(HTML ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...