react 类组件的生命周期
一个小问题
问题:componentDidMount 生命周期函数执行两次,直接关闭react的严格模式即可
严格模式下的代码:
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
非严格模式下的代码:
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<App />)
备注1:严格模式检查仅在开发模式下运行,它们不会影响生产版本。
备注2: <React.StrictMode> </React.StrictMode> 组件不仅可以包裹根组件,也可以包裹部分组件,这意味着仅对部分react代码启动严格模式。
import React from 'react';
function ExampleApplication() {
return (
<div>
<Header />
<React.StrictMode>
<div>
<ComponentOne />
<ComponentTwo />
</div>
</React.StrictMode>
<Footer />
</div>
);
}
react 类组件生命周期
react-16.4 的生命周期如上图所示,分为三个阶段,分别是:
mounting(初始化渲染阶段/创建时)->updating(更新阶段/更新时)->unMounting(卸载阶段/卸载时)
图示解读:
1. 初始化阶段
constructor() -> render() -> componentDidMount()
constructor()
该生命周期中一般可以用来初始化state
componentDidMount()
该生命周期中,dom已经挂载,可以获取dom,进行dom相关的操作,以及请求数据
2. 更新阶段
render() -> shouldComponentUpdate() -> componentDidUpdate()
shouldComponentUpdate(nextProps, nextState)
该生命周期可以获取到最新的属性和状态,该生命周期必须有一个返回值,返回true则执行render方法,返回false则不执行render方法。可以做一些性能优化,但是官方不建议这样做,容易触发bug。
componentDidUpdate(prevProps, prevState)
该方法可以获取到更新之前的属性和状态。这个生命周期容易造成死循环,慎用。
3. 卸载阶段
-> componentWillUnmount()
该生命周期函数可以清除定时器,解绑dom事件,清楚网络状态。
测试代码:
App.js
import React, { Component } from "react"
import PageA from "./pages/pageA"
import PageB from "./pages/pageB"
export default class App extends Component {
state = {
flag: true,
pageATitle: "pageA的标题",
pageBTitle: "pageB的标题"
}
render() {
return (
<>
<button
onClick={() => {
this.setState({ flag: !this.state.flag })
}}
>
切换组件
</button>
<button
onClick={() => {
this.setState({ pageATitle: "新的pageA的标题" })
}}
>
更新组件A的props
</button>
<button
onClick={() => {
this.setState({ pageBTitle: "新的pageB的标题" })
}}
>
更新组件B的props
</button>
<hr />
{this.state.flag && <PageA title={this.state.pageATitle} />}
{!this.state.flag && <PageB title={this.state.pageBTitle} />}
</>
)
}
}
PageA.js
import React, { Component } from "react"
export default class PageA extends Component {
render() {
return <div>PageA-{this.props.title}</div>
}
componentDidMount() {
console.log("PageA-componentDidMount-加载了")
}
shouldComponentUpdate(nextProps, nextState) {
console.log("nextProps", nextProps)
console.log("nextState", nextState)
return true
}
componentDidUpdate(prevProps, prevState) {
console.log("prevProps", prevProps)
console.log("prevState", prevState)
}
componentWillUnmount() {
console.log("PageA-componentWillUnmount-组件被卸载了")
}
}
PageB.js
import React, { Component } from "react"
export default class PageB extends Component {
render() {
return <div>PageB-{this.props.title}</div>
}
componentDidMount() {
console.log("PageB-componentDidMount-加载了")
}
shouldComponentUpdate(nextProps, nextState) {
console.log("nextProps", nextProps)
console.log("nextState", nextState)
return true
}
componentDidUpdate(prevProps, prevState) {
console.log("prevProps", prevProps)
console.log("prevState", prevState)
}
componentWillUnmount() {
console.log("PageB-componentWillUnmount-组件被卸载了")
}
}
官方建议
shouldComponentUpdate() 仅作为性能优化的方式而存在,不要企图依靠此方法来 “阻止” 渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写。
操作:
import React, { PureComponent } from "react"
export default class PageB extends PureComponent {
render() {
return <div>PageB-{this.props.title}</div>
}
componentDidMount() {
console.log("PageB-componentDidMount-加载了")
}
componentDidUpdate(prevProps, prevState) {
console.log("prevProps", prevProps)
console.log("prevState", prevState)
}
componentWillUnmount() {
console.log("PageB-componentWillUnmount-组件被卸载了")
}
}