React setState一些解析以及 react性能优化

详解setState

1.开发中我们并不能直接通过修改state的值来让界面发生更新:
  • 因为我们修改了state之后,希望React根据最新的State来重新渲染界面,但是这种方式的修改React并不知道数据发生了变化;
  • React并没有实现类似于Vue2中的Object.defineProperty或者Vue3中的Proxy的方式来监听数据的变化;
  • 我们必须通过setState来告知React数据E经发生了变化;
2.setState函数是我们继承的Component原型中定义的。
3.setState是异步更新的
  • 我们不能在执行完setState之后立马拿到最新的state的结果。
export default class App extends Component {
    constructor(props){
        super(props);

        this.state = {
            message:'setState的更新方式'
        }
    }

    render() {
        return (
            <div>
                <h2>setState的更新方式</h2>
                <button onClick={e => this.changeText()}>修改setstate</button>
            </div>
        )
    }

    changeText(){
        this.setState({
            message:'setState是异步更新的'
        })
        
        console.log(this.state.message)  //setState的更新方式
    }
}

  • react异步更新的好处
    • setState设计为异步,可以显著的提升性能;如果每次调用setState都进行一次更新,那么意味着render函数会被频繁调用,界面
      重新渲染,这样效率是很低的;最好的办法应该是获取到多个更新,之后进行批量更新;
    • 如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步;state和props不能保持一致性,会在开发中产生很多的问题;
4.那么如何获取到异步更新后的数据呢?
  • 方式1:
/**
 * 方式1:获取异步更新后的数据
 * setState可以传入一个回调函数
 */

    this.setState({
        message:"happy birthday!"
    },() => {
        console.log(this.state.message)
    })
  • 方式2:使用生命周期函数
componentDidUpdate(){
        console.log(this.state.message)
    }
5.两种方式让setState实现同步更新
  • 情况1:将setState放进定时器中
/**
 * 两种方式让setState实现同步更新
 * 方式1:将setState放进定时器中
 */
setTimeout(() => {
    this.setState({
        message:'happy birthday!'
    })

    console.log(this.state.message)
})
  • 情况2:使用原始的DOM事件监听
componentDidMount(){
        document.getElementById('btn').addEventListener('click',()=>{
            this.setState({
                message:'happy birthday!'
            })

            console.log(this.state.message)
        })
    }
6.setState实现了数据合并和自身合并
  • 利用了Object.assign() 将两个对象实现了合并。

  • 当你调用了三次setState时,内部会发生合并。

详解React更新机制

1.react渲染流程

JSX - 虚拟DOM - 真实DOM

2.React更新流程

props/state改变 -> render函数重新执行 -> 产生新的DOM树
-> 新旧DOM树进行diff算法 -> 计算出差异进行更新 -> 更新到真实的DOM

  • props/state改变,会调用React的render方法,创建一颗不同的树

在这里插入图片描述
在这里插入图片描述

React性能优化

1.react性能优化 — keys

在这里插入图片描述

2.react性能优化 — render()
  • shouldComponentUpdata()
    /**

    • 我们需要将组件更新给修改为不调用render函数
    • shouldComponentUpdate()
    • 返回值为true:那么就需要调用render方法
    • 返回值为false:那么就不需要调用render方法
    • shouldComponentUpdate()传过来了两个参数
    • nextProps, nextState
    • nextProps : 最新的props
    • nextState : 最新的state
      */
  • PureComponent可以阻止类组件的不必要多次render()更新 PureComponent 中对props和state进行了浅层比较

class Son extends PureComponent{
    render(){
        console.log('son被调用')
        return <h2>我是Son组件</h2>
    }
}

export default class App extends PureComponent {


    constructor(props){
        super(props);

        this.state = {
            counter:0
        }
    }

    render() {
        console.log('App被调用')
        return (
            <div>
                <h2>我是最大的组件</h2>
                <Son/>
                <h2>当前计数:{this.state.counter}</h2>

                <button onClick={ e => this.counterAdd()}>+1</button>
            </div>
        )
    }
    counterAdd(){
        this.setState({
            counter:this.state.counter+1
        })
    }

    changeText(){
        this.setState({
            message:'你好,中国'
        })
    }
}
  • 但是无论是shouldComponentUpdate() 还是PureComponent都只能组织类组件的render更新

  • 那么如何解决函数式组件每次被调用 memo(高阶组件)的使用
    memo() 的参数是传入一个函数式组件

import React, { PureComponent, memo } from 'react'

class Son extends PureComponent{
    render(){
        console.log('son被调用')
        return <h2>我是Son组件</h2>
    }
}

const MemoSon2 = memo(
    function Son2(){
    console.log('son2被调用')
    return <h2>我是组件son2</h2>
}
)

export default class App extends PureComponent {


    constructor(props){
        super(props);

        this.state = {
            counter:0
        }
    }

    render() {
        console.log('App被调用')
        return (
            <div>
                <h2>我是最大的组件</h2>
                <MemoSon2/>
                <Son/>
                <h2>当前计数:{this.state.counter}</h2>

                <button onClick={ e => this.counterAdd()}>+1</button>
            </div>
        )
    }

    counterAdd(){
        this.setState({
            counter:this.state.counter+1
        })
    }

    changeText(){
        this.setState({
            message:'你好,中国'
        })
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值