react-3-2

66 阅读2分钟

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 类组件生命周期

image-20221005161453613.png

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-组件被卸载了")
  }
}