React的数据不可变shallow merge

410 阅读1分钟

React有一个特点就是数据不可变,当这个数据改变时他不会真正改变这个数据的值,而是再生成一个对象

做一个+1的案例

使用this.state.n+=1后页面的数据不会刷新,因为没有只不过时UI没有更新this.state.n+=1;应该使用this.setState({ n: this.state.n + 1 })生成一个新的对象,调用setState才会触发跟新

class Son extends React.Component{
    //类组件的数据初始化,super()必须要写否则报错
    constructor(){
        super()
        this.state={
            n:0
        };
    };
    add(){
        // this.state.n+=1
        this.setState({ n: this.state.n + 1 });
        console.log(this.state.n) //0
    };

此时打印出的是0,因为要等这个方法全部完成之后新的值才会覆盖原先的值,setState是一个异步方法,不会马上去修改state

类组件自动合并,函数组件不会自动合并

setState会自动合并第一层属性,但是不会自动合并第二层

此时的n和m是第一层属性;只改变一个n的值,另一个m如果没有修改就不会改变,m按原样不变

class Son extends React.Component{
    constructor(){
        super()
        this.state={
            n:0
            m:0
        };
    };
    add(){
        this.setState({
            (state)=>{
                const n = state.n+1
                return {n:n}
            }
        })

    };

添加一个user对象,user对象里的属性就属于第二层属性

此时只改变第二层属性里的name,age不变,但是最后结果age会被置空(age丢失),age会变成undefined

class Son extends React.Component{
    constructor(){
        super()
        this.state={
            n:0,
            m:0,
            user:{
                name:dong,
                age:18
            }
        };
    };
    changeUser(){
        this.setState({
            user:{
                name:"jack"
            }
        })

    };

解决方法

解决方法是使用扩展运算符先将原先的属性复制过来,再改其中的属性

 changeUser(){
        this.setState({
            user:{
                ...this.state.user,
                name:"jack"
            }
        })
        
//或者这样写,会把this.state.user拷贝到{}这个新对象上边,然后新对象再赋值给user
const user = Object.assign({},this.state.user);