React組件的生命周期深入理解分析
組件從創(chuàng)建到銷毀的過程,被稱為組件的生命周期。
在生命周期的各個(gè)階段都有相對應(yīng)的鉤子函數(shù),會在特定的時(shí)機(jī)被調(diào)用,被稱為組件的生命周期鉤子。
生命周期回調(diào)函數(shù) = 生命周期鉤子函數(shù) = 生命周期函數(shù) = 生命周期鉤子
函數(shù)式組件沒有生命周期,因?yàn)樯芷诤瘮?shù)是 React.Component 類的方法實(shí)現(xiàn)的,函數(shù)式組件沒有繼承 React.Component,所以也就沒有生命周期。
<-- 容器!-->
<div id="test"></div>
// 創(chuàng)建組件
class Life extends React.Component{
state = {opacity:1}
// 調(diào)用時(shí)機(jī):組件掛載完畢
componentDidMount(){
this.timer = setInterval(() => {
let {opacity} = this.state
opacity -= 0.1
if(opacity <= 0) opacity = 1
this.setState({opacity})
}, 200);
}
//調(diào)用時(shí)機(jī):組件將要卸載
componentWillUnmount(){
clearInterval(this.timer)
}
handleUnmount = ()=>{
//卸載組件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
//調(diào)用時(shí)機(jī):初始化渲染、狀態(tài)更新之后
render(){
return(
<div>
<h2 style={{opacity:this.state.opacity}}>我是一段透明度會變化的文字</h2>
<button onClick={this.handleUnmount}>點(diǎn)擊卸載</button>
</div>
)
}
}
//渲染組件
ReactDOM.render(<Life/>,document.getElementById('test'))
生命周期鉤子(新)
新的生命周期鉤子增加了 getDerivedStateFromProps 和 getSnapshotBeforeUpdate。

constructor():constructor() 構(gòu)造函數(shù)在 React 組件掛載之前被調(diào)用。
如果不初始化 state 或不為事件處理函數(shù)綁定實(shí)例,則不需要寫 constructor()。
不能在 constructor() 構(gòu)造函數(shù)內(nèi)部調(diào)用 this.setState(), 因?yàn)榇藭r(shí)第一次 render() 還未執(zhí)行,也就意味 DOM 節(jié)點(diǎn)還未掛載。
static getDerivedStateFromProps(nextProps, prevState):在每次調(diào)用 render() 方法之前都會被調(diào)用,在初始化和更新時(shí)都會被調(diào)用。
getDerivedStateFromProps() 第一個(gè)參數(shù)為即將更新的 props,第二個(gè)參數(shù)為上一個(gè)狀態(tài)的 state,可以比較 props 和 state 來加一些限制條件,防止無用的 state 更新。
getDerivedStateFromProps() 的返回值是必須的。返回一個(gè)對象來更新 state,如果不需要更新,返回 null 即可。 getDerivedStateFromProps() 適用于 state 的值在任何時(shí)候都取決于 props 的情況。 getDerivedStateFromProps() 是一個(gè)靜態(tài)函數(shù),是放在組件身上的,而不是放在組件實(shí)例身上,因此不能使用 this。
// 之前使用 componentWillReceiveProps
componentWillReceiveProps(nextProps) {
if (nextProps.location.search !== this.props.location.search) {
this.init()
}
}
// 現(xiàn)在使用 getDerivedStateFromProps:相當(dāng)于把 componentWillReceiveProps 拆分成 getDerivedStateFromProps 和 componentDidUpdate
static getDerivedStateFromProps(nextProps, prevState) {
const {search} = nextProps.location
if (search !== prevState.search) {
return {
search,
}
}
return null
}
componentDidUpdate(prevProps, prevState) {
const {search} = this.state
if (search !== prevState.search) {
this.init()
}
}
render():render() 方法是類組件中唯一必須實(shí)現(xiàn)的方法,用于渲染 DOM,render() 方法必須返回 reactDOM。
在 render() 的 return 之前不能寫 setState,否則會觸發(fā)死循環(huán)導(dǎo)致內(nèi)存崩潰;return 體里面是可以寫的。
// Wrong
render(){
this.setState({...})
return (...)
}
// Correct
render(){
return (
<input onClick={()=>this.setState({...})} />
)
}componentDidMount():在組件掛載后 (插入 DOM 樹后) 立即調(diào)用,此生命周期是發(fā)送網(wǎng)絡(luò)請求、開啟定時(shí)器、訂閱消息等的好時(shí)機(jī),并且可以在此鉤子函數(shù)里直接調(diào)用 setState()。
shouldComponentUpdate(nextProps, nextState):在組件更新之前調(diào)用,可以控制組件是否進(jìn)行更新, 返回 true 時(shí)組件更新, 返回 false 則不更新。不寫此生命周期鉤子時(shí)默認(rèn)為 true。
shouldComponentUpdate() 第一個(gè)參數(shù)是即將更新的 props 值,第二個(gè)參數(shù)是即將更新后的 state 值,可以根據(jù)更新前后的 props 或 state 來比較加一些限制條件,決定是否更新,進(jìn)行性能優(yōu)化。
不要在 shouldComponentUpdate 中調(diào)用 setState(),否則會導(dǎo)致無限循環(huán)調(diào)用更新、渲染,直至瀏覽器內(nèi)存崩潰。
getSnapshotBeforeUpdate(prevProps, prevState):在最新的渲染數(shù)據(jù)提交給 DOM 前會調(diào)用,也就是說,在 render 之后,在 componentDidUpdate 之前調(diào)用。使得組件可以在更新之前獲取快照值。不常用。
它可以使組件在 DOM 真正更新之前捕獲一些信息(例如滾動(dòng)位置),此生命周期返回的任何值都會作為參數(shù)傳遞給 componentDidUpdate(),如不需要傳遞任何值,那么返回 null。返回值是必須的。
componentDidUpdate(prevProps, prevState, snapshot):componentDidUpdate() 會在更新后會被立即調(diào)用。首次渲染不會執(zhí)行。
包含三個(gè)參數(shù),第一個(gè)是上一次props值。 第二個(gè)是上一次state值,第三個(gè)是“snapshot” 參數(shù)傳遞。
可以進(jìn)行前后 props 的比較進(jìn)行條件語句的限制,來進(jìn)行 setState() , 否則會導(dǎo)致死循環(huán)。
componentWillUnmount():componentWillUnmount() 在組件即將被卸載或銷毀時(shí)進(jìn)行調(diào)用。此生命周期是清理定時(shí)器、取消訂閱等操作的好時(shí)機(jī)。
組件的掛載流程:
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
setState 更新流程:
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
組件的卸載流程: componentWillUnmount
生命周期鉤子(舊)
React 從 v16.3 開始廢棄 componentWillMount、componentWillReceiveProps、componentWillUpdate 三個(gè)鉤子函數(shù)。在新版本中使用需要加上 UNSAFE_ 前綴,否則會觸發(fā)控制臺的警告。
UNSAFE 不是指安全性,而是表示使用這些生命周期的代碼在 React 的未來版本中更有可能出現(xiàn) Bug,尤其是在啟用異步渲染之后。

組件的掛載流程:
- constructor
- componentWillMount
- render
- componentDidMount
setState 更新流程:
- shouldComponentUpdate
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
forceUpdate 強(qiáng)制更新流程:
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
父組件 render 之后子組件的更新流程:
- componentWillReceiveProps(子組件接收到新的 props 之前調(diào)用,第一次接收到 props 不會調(diào)用)
componentWillReceiveProps(nextProps) {
// 可以和 this.props 中的數(shù)據(jù)進(jìn)行對比,以決定是否要執(zhí)行某些方法
}
- shouldComponentUpdate
- componentWillUpdate(組件更新之前調(diào)用)
- render
- componentDidUpdate
組件的卸載流程:
componentWillUnmount
父子組件生命周期
當(dāng)子組件自身的 state 狀態(tài)改變,不會對父組件產(chǎn)生副作用的情況下,父組件不會進(jìn)行更新,也就是不會觸發(fā)父組件的生命周期。
當(dāng)父組件狀態(tài)變化時(shí)(不會是否更改到傳給子組件的 props),會觸發(fā)自身和子組件對應(yīng)的生命周期。
render 以及 render 之前的生命周期,父組件先執(zhí)行;
render 之后的生命周期,子組件先執(zhí)行,并且是與父組件交替執(zhí)行。
父子組件初始化流程:
- 父組件constructor
- 父組件getDerivedStateFromProps
- 父組件render
- 子組件constructor
- 子組件getDerivedStateFromProps
- 子組件render
- 子組件componentDidMount
- 父組件componentDidMount
子組件修改自身的 state 狀態(tài)流程:
- 子組件getDerivedStateFromProps
- 子組件shouldComponentUpdate
- 子組件render
- 子組件getSnapshotBeforeUpdate
- 子組件componentDidUpdate
父組件修改 state 狀態(tài)流程:
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 子組件getDerivedStateFromProps
- 子組件shouldComponentUpdate
- 子組件render
- 子組件getSnapshotBeforeUpdate
- 父組件getSnapshotBeforeUpdate
- 子組件componentDidUpdate
- 父組件componentDidUpdate
父組件卸載子組件:
// 通過點(diǎn)擊父組件中的 [卸載 / 掛載子組件] 按鈕來卸載子組件
handelToggle = () => {
this.setState({
isHidden: !this.state.isHidden
})
}
<button onClick={this.handelToggle}>掛載/卸載子組件</button>
{this.state.isHidden ? '' : <Child />>}
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 父組件getSnapshotBeforeUpdate
- 子組件componentWillUnmount
- 組件componentDidUpdate
父組件重新掛載子組件:
再次點(diǎn)擊父組件中的 [卸載 / 掛載子組件] 按鈕來掛載子組件。
- 父組件getDerivedStateFromProps
- 父組件shouldComponentUpdate
- 父組件render
- 子組件constructor
- 子組件getDerivedStateFromProps
- 子組件render
- 父組件getSnapshotBeforeUpdate
- 子組件componentDidMount
- 父組件componentDidUpdate
到此這篇關(guān)于React組件的生命周期深入理解分析的文章就介紹到這了,更多相關(guān)React組件的生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React中useTransition鉤子函數(shù)的使用詳解
React?18的推出標(biāo)志著React并發(fā)特性的正式到來,其中useTransition鉤子函數(shù)是一個(gè)重要的新增功能,下面我們就來學(xué)習(xí)一下useTransition鉤子函數(shù)的具體使用吧2024-02-02
React文件名和目錄規(guī)范最佳實(shí)踐記錄(總結(jié)篇)
React在使用時(shí)非常靈活,如果沒有一個(gè)規(guī)范約束項(xiàng)目,在開發(fā)過程中會非?;靵y,本文將介紹幾個(gè)優(yōu)秀的規(guī)范,介紹文件名和目錄前,需要先簡述一下幾種通用的類型,用來區(qū)分文件的功能,感興趣的朋友一起看看吧2022-05-05
React + webpack 環(huán)境配置的方法步驟
本篇文章主要介紹了React + webpack 環(huán)境配置的方法步驟,詳解的介紹了開發(fā)環(huán)境的配置搭建,有興趣的可以了解一下2017-09-09
一文搞懂?React?18?中的?useTransition()?與?useDeferredValue()
這篇文章主要介紹了一文搞懂?React?18?中的?useTransition()與useDeferredValue(),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09
react配置webpack-bundle-analyzer項(xiàng)目優(yōu)化踩坑記錄
這篇文章主要介紹了react配置webpack-bundle-analyzer項(xiàng)目優(yōu)化踩坑記錄,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
Next.js搭建Monorepo組件庫文檔實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Next.js搭建Monorepo組件庫文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
react 項(xiàng)目 中使用 Dllplugin 打包優(yōu)化技巧
在用 Webpack 打包的時(shí)候,對于一些不經(jīng)常更新的第三方庫,比如 react,lodash,vue 我們希望能和自己的代碼分離開,這篇文章主要介紹了react 項(xiàng)目 中 使用 Dllplugin 打包優(yōu)化,需要的朋友可以參考下2023-01-01

