React 生命周期 及setState()

604 阅读2分钟

一 、React 生命周期(类组件)

image.png

(v16.3之后)react 生命周期 分为三个阶段

  • 1 挂载阶段
    contructor() 该钩子用于 初始化 state ,以及创建ref
    render()
    componentDidMount() 挂载完成是的钩子 可以获取渲染好的dom

  • 2 更新阶段 render()
    componentDidUpdate() 组件完成更新是=时的钩子

  • 3 卸载阶段 componentWillUnmount() 组件即将卸载时的钩子 (一般用于清除定时器,解绑事件等)

tip

 render() ,componentDidUpdate() 这两个钩子中不可以直接使用setState()  state 发生变化会引起重新渲染 执行 render() render() 又会执行setState() 导致死循环

二 、 setState 更新数据的表现

  • 一般情况下(常见的在生命周期或合成事件处理函数中),通过 setState() 方法来更新数据,表现是异步的。
  • 当执行到 setState 这一行的时候,React 出于性能考虑,并不会马上进行调用来修改 state,而是先把这个以及后续的更新对象放到一个更新队列里面进行合并的操作,期间不影响后续代码的执行。
  • 多次调用 setState(),只会触发一次重新渲染,所以无需担心多次进行 setState 会带来性能问题

// 初始
state = { count: 1 }
// 更新
this.setState({
    count: this.state.count + 1,
})
// 输出
console.log(this.state.count) // 1
// 通过 DOM 也是不能马上获取的

解释合并


this.setState({
    count: this.state.count + 1,
})
this.setState({
    count: this.state.count + 2,
})
this.setState({
    count: this.state.count + 1,
})

同步表现

如果是在 setTimeout/setInterval 或者原生事件的回调中,表现出来是同步的。


import React, { Component } from 'react'

export default class App extends Component {
    state = {
        count: 1,
    }
    componentDidMount() {
        setTimeout(() => {
            this.setState({
                count: this.state.count + 1,
            })
            console.log(this.state.count) // 2
        })
    }
    render() {
        return <div>{this.state.count}</div>
    }
}

原生事件


import React, { Component, createRef } from 'react'

export default class App extends Component {
    state = {
        count: 1,
    }
    btnRef = createRef()
    componentDidMount() {
        this.btnRef.current.onclick = () => {
            this.setState({
                count: this.state.count + 1,
            })
            console.log(this.state.count) // 2
        }
    }
    render() {
        return (
            <div>
                <h2>{this.state.count}</h2>
                <button ref={this.btnRef}>click</button>
            </div>
        )
    }
}

tip

  • 问题/现象:不能立即拿到更新后的数据;多次进行 setState 会进行合并的操作。 1、解决 不能立即拿到更新后的数据 通过 setState 第二个参数可以立即拿到更新后的数据。

  • 场景:在状态更新后,依靠更新后的状态立即执行某个操作。

  • 语法:setState(updater[, callback])


this.setState({}, () => {
    console.log('这个回调函数会在状态更新后立即执行')
})

2、解决 多次进行 setState 会进行合并的操作。

  • 使用 setState((preState) => {}) 语法。
  • 参数 preState: 上一个 setState 的结果。
// 初始\
state = { count: 1 }\
\
// 更新\
this.setState((preState) => {\
return {\
count: preState.count + 1,\
}\
})\
\
this.setState((preState) => {\
return {\
count: preState.count + 2,\
}\
})\
\
// 输出\
console.log(this.state.count) // 依然是 1\

这种语法依旧是异步的,不同的是通过 preState 可以获取到最新的状态。