React里的一些神坑,持续更新ing

1.对于react内对state状态修改的性能优化
对于同一时间段相同事件的重复触发,正常情况下,react会进行性能优化,比如

state={
	count:0
}
for(let i=0;i<100;i++){
	this.setState({
            count:this.state.count + 1
     }
     console.log(this.state.count) //输出100次0
}

这样的话只会输出一百次0,而count的值会变为99,这就是react自身的性能优化,将短时间内多次相同的事件合并在一起处理
但是!!!,如果代码这样写的话

state={
	count:0
}
for(let i=0;i<100;i++){
	this.setState({
            count:++this.state.count 
     }
     console.log(this.state.count) //1,2,3,...99
}

这样的话,输出的值从0开始到99结束,每循环一次都会输出一次,这样的代码是不存在合并的

2.对于类组件更改state的同步异步的问题

state={
	count:0
}
//修改state的第一种方法,在setState的第一个参数写对象,一般来说是同步
increment=()=>{
	this.setState({
            count:++this.state.count 
     }}
     console.log(this.state.count)
}
  //修改state的第二种方法,在setState的第一个参数写回调函数,一般来说是异步
  increment=()=>{
		this.setState(({count}) =>{
            return {
                count:++this.state.count 
            }
        })
        console.log(this.state.count)
	}
	

上面两种方法,需要去触发increment函数,在第一种方法里,输出的值和修改后的count保持同步更新,所以一般来说是同步的,而第二种里输出的值一般是上一次的count值,会比最新的修改的count值慢一次更新,所以一般是异步的,但是在第二种方法里也是可以获取最新的count,那就需要在this.setState的第二个参数写回调函数

		this.setState(({count}) =>{
            return {
                count:++this.state.count
            }
        },() =>{
            //这里可以获取最新的状态
            console.log(this.state.count)
        })

但是!!!,如果两个修改的方法不是前置++,而是如代码所示

state={
	count:0
}
//修改state的第一种方法,在setState的第一个参数写对象,是异步
increment=()=>{
	this.setState({
            count:this.state.count +1
     }}
     console.log(this.state.count)
}
  //修改state的第二种方法,在setState的第一个参数写回调函数,是异步
  increment=()=>{
		this.setState(({count}) =>{
            return {
                count:this.state.count +1
            }
        })
        console.log(this.state.count)
	}

上面的输出的值,都是最新修改count值的上一次值,也就是说比最新的慢一个,当然了,在this.setState的第二个参数写回调函数还是可以获取最新的count值。

与此相同的还有就是,不是对state内的值进行简单的加减,而是直接赋值的话,如代码所示

state={
	url:'aaa'
}
//修改state的第一种方法,在setState的第一个参数写对象,是异步
increment=()=>{
	this.setState({
            url.'bbb'
     }}
     console.log(this.state.url) //aaa,如果触发两次就会输出bbb
}
  //修改state的第二种方法,在setState的第一个参数写回调函数,是异步
  increment=()=>{
		this.setState(({url}) =>{
            return {
                url:'bbb'
            }
        })
        console.log(this.state.url) //aaa,如果触发两次就会输出bbb
	}

上面对state内的url进行修改,然后获取的url值依旧是aaa,而不是bbb,当然,state内的url确实是修改了,但是这里还有存在异步的问题,所以只能获取上一次的url

3.在类组件中的方法都要写成箭头函数的原因

export default class Hello extends Component {
	state={
		name:"iron"
	}
	//这里的函数要写成箭头函数,才不会影响里面this.setState的使用
	hender=()=>{
		this.setState({
			name:"superstar"
		})
	}
    render(){
        return (
            <div>
                <button  onClick={this.hander}>点击按钮</button>
            </div>
        )
    }
}

为什么里面的函数就一定要写成箭头函数才不会影响,其实这个和原生js面向对象语法糖里的this指向类似,都是为了写在button标签内的this.hander中的this指向,在button里的this指向的是button,就相对于在原生面向对象的函数内再写鼠标移动事件,那么这个鼠标移动事件就要写成箭头函数才行,不然就会影响事件内的this指向,所以了解这个之后,react内的函数也可以不写成箭头函数,如下代码

export default class LayOut extends React.Component {
    constructor(props){
        super(props)
        this.state={
            name:"iron"
        }
        //在constructor里修改this指向
        this.hander4 = this.hander4.bind(this)
    }

    hander1=()=>{
        this.setState({
            name:"superstar1"
        })
    }
    hander2(){
        this.setState({
            name:"superstar2"
        })
    }
    hander3(){
        this.setState({
            name:"superstar3"
        })
    }
    hander4(){
        this.setState({
            name:"superstar4"
        })
    }

    render(){
        return (
            <div>
            	//使用箭头函数
                <button  onClick={this.hander1}>点击按钮1</button><hr/>
                //只要button标签不会影响this指向
                <button  onClick={()=>{this.hander2()}}>点击按钮2</button><hr/>
                //直接修改this指向
                <button  onClick={this.hander3.bind(this)}>点击按钮3</button><hr/>
                //在constructor里先修改好
                <button  onClick={this.hander4}>点击按钮4</button><hr/><hr/>
                {this.state.name}
            </div>
        )
    }
}

对啦,对于constructor和render里是不需要使用箭头函数也不会影响this指向的,因为这两个是react生命周期初始化阶段的钩子函数,当然了,使用了箭头函数也没关系,不影响

4.react里去使用数组方法的注意事项

export default class LayOut extends React.Component {
    constructor(props){
        super(props)
        this.state={
            arr:[1,2,3]
        }
    }

    hander1=()=>{
        let num = 5
        //测试一:直接去修改状态内的arr,这样是可以的
         this.state.arr.push(num) 
        console.log(this.state.arr)//[1,2,3,5],这样可以获取最新的值
         //测试二:使用解构赋值,这样是可以的
        this.setState({
            arr:[num,... this.state.arr] 
        },()=>{
            console.log(this.state.arr)//[1,2,3,5]
        })
        console.log(this.state.arr)//[1,2,3] 异步方法,无法立刻获取修改后的值
        //测试三:将修改后的值赋值与状态内的arr,有问题
        this.setState({
            arr:this.state.arr.push(num) 
        },()=>{
            console.log(this.state.arr)//4
        })
        //测试四:针对上面的问题,再次测试
        const name = this.state.arr.push(num) 
        console.log(this.state.arr)//[1,2,3,5]
        console.log(name) //4
    }
    render=()=>{
        return (
            <div>
                <button  onClick={this.hander1}>点击按钮1</button><hr/>
            </div>
        )
    }
}

有以上代码可以看出,直接去修改组件的状态是可以的,但是不能将修改后的值再赋予状态内的值,这是因为数组push的返回值是改变后的数组长度

还有其他数组的使用方法可以参考该博主的博客
https://blog.csdn.net/hahahhahahahha123456/article/details/104922711

5.在react生命周期更新阶段过程
在react生命周期的更新阶段,他有5个钩子函数,正确的说,对于属性是5个钩子函数,对于状态state的更新只有4个钩子函数,具体的可以看我写的生命周期的博客,这里要说的是两者都有的shouldComponentUpdate(nextProps,nextState){}这个钩子函数,这个钩子函数是用来判断数据是否有变化的,如果数据没有变化,那就不进行数据的渲染,而一般采用浅比较,也就是直接比较会发生变化的属性或者状态,不可以比较nextProps和this.props或者nextState和this.state,因为都是对象,对象的地址不相同的,那么两者肯定不同,这就达不到我们需要的比较效果了。
值得注意的是
- nextState 和 this.state【新值】 是一样的【值】,所以要自己去设定 一个值进行比较,要注意异步的问题
- nextProps 和 this.props【旧值】
那么如何去设定一个值用于自己在状态改变的时候进行比较,我们需要在state里添加一个状态用于保存变化的状态的前一个值,但是我们又要注意,像如下代码

constructor(props){
        super(props)
        this.state={
            count:0,
            n:0
        }
    }

    hander=()=>{
        this.setState({
            n:this.state.count + 1,
            count:++this.state.count
        })
    }

对于n的修改,前置++是可以保持同步更新的,而后置加1是无法保持同步更新的,所以这样正好可以获取我们需要的count的前一个值,我们不可以n:this.state.count,因为直接赋值也是异步,这样我们会和count相差两个次的变化,会出现错误

6.更多神坑等待更新ing

以上都是个人见解,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值