筑基 -React state与setState的三种使用方式

634 阅读3分钟
react 知识点一 props 
组件通信就靠props
(context mobx redux 还没开始讲)
另一个大知识就是state 

props 为只读,而且不能修改,只能做接收使用
当前组件中如何使用state 以及修改state 呢
我们来看内容

新建一个页面

react/first-react/src/App.js

1导入
import State from './views/State';

2引入
<State/>

对应建文件

vi src/views/State/index.jsx
除了 render函数 我们今天新增一个 constructor

constructor 主要两个作用,
1、state 初始化
2、邦定实例  (在事件内容章节会讲)

所以我们来开始看代码

constructor(props){
    super(props)
    this.state = {
        'name':'元芳',
    }
}

render(){
    //可以直接使用 this.state.name 
    // 是不是可props一样呀,
    // 单我们都知道要重构代码
    let {name} = this.state;
    return(
        <div>
            <h3>state</h3>
            名字是:{this.state.name}<br/>
            {name}<br/>
        </div>
    )
}
我们现在要做的就是来改变名字

接触另一个周期函数
componentDidMount  具体在生命周期章节讲
函数的主要作用是 挂载完成,ajax 请求  方法初始化 以及设定定时器
componentDidMount(){
    this.setState({
        name:'小金'
    })
}
改变state 的唯一方法就是setState 
不可以this.state.name = '' 这是不可以的
需要setState

所以setState 的第一种方式是 直接赋值
this.setState({
    name:'1'
})

改现在问题来了
constructor 中
this.state = {
    'info':{
        'name':'小明',
        'age':32
    }
}
现在要直接改变info 中的name 
age 或假如有其他更多信息时都不改变
那我们常规写法
this.setState({
    'info':{
        'name':'金子'
    }
})
此方法不成立,看代码就可以看出来
相当于我们把info 重新赋了一个对象
那这种情况应该怎么写
--
思考一下,这是不是相当于合并对象,保留原有的,覆盖或增加新的,那知道点就来了
见代码

this.setState({
    info:Object.assign({},
        this.state.info,
        {name:'李元芳'}
    )
})
这样是不是就是把原有的和新改的合并啦
问题就解决了,那除了这个方法还有什么?
this.setState({
    info:{
        ...this.state.info,
        name:'李元芳'
    )
})
这样我们就可以改变单个state 的值以及 对象某的某一个值了。

所以第二种方式是 通过合并对象的方式来修改 state 对象中的某一值
根据官网介绍,setState 可能是异步的,
所以 我们在正常
this.setState({
    info:{
        ...this.state.info,
        age:32+1
    }
})
console.log(this.state.info.age) 有时候是拿不到这个值的

那问题来了,如果我们想改变 自身的值  
比如age+1 怎么实现

this.setState()接收一个函数

//this.setState(function(state,props){
//     console.log(state)
//     console.log(props)
//     return{
//         info:{
//             ..._this.state.info,
//             age:state.info.age+1
//         }
//     }
// })
// this.setState((state,props)=>{
//     return{
//         info:{
//             ...this.state.info,
//             age:state.info.age+1
//         }
//     }
// })
this.setState((state,props)=>{
    return({
            info:{
                ...this.state.info,
                age:state.info.age+1
            }
    })
})
能看到代码变化吧
下面的代码是我们改变自身的值的使用方式
接受一个箭头函数
通过参数来接收上一次的值,从而达到改变
this.setState((state,props)=>({
    info:{
        ...this.state.info,
        age:state.info.age+1
    }
}))

setState 的注意事项

三种使用方式
1、直接赋值
2、改变对象中的某一个值
3、改变自身的值

二、setState 后的render 执行一次
componentDidMount 中调用了多个函数,并且在每个函数中有一个或多个setState 

那么正常是合并的方式,render 只会执行一次

如果中间使用了 setTimeout  ajax 等异步操作
render 会单独执行一次



完整代码

react/first-react/src/views/State/index.jsx
import React, { Component } from 'react';

class View extends Component {
    constructor(props){
        super(props)
        this.state = {
            'name':'元芳',
            'info':{
                'name':'小明',
                'age':32
            }
        }
    }
    changeInfo(){
        this.setState({
            name:'小红',
            info:{
                name:'李元芳',
                age:32
            },
            // info:{
            //     ...this.state.info,
            //     name:'李元芳'
            // }
            info:Object.assign({},
                this.state.info,
                {name:'李元芳'}
            )
        })
    }
    addAge(){
        // let _this = this;
        // this.setState(function(state,props){
        //     console.log(state)
        //     console.log(props)
        //     return{
        //         info:{
        //             ..._this.state.info,
        //             age:state.info.age+1
        //         }
        //     }
        // })
        // this.setState((state,props)=>{
        //     return{
        //         info:{
        //             ...this.state.info,
        //             age:state.info.age+1
        //         }
        //     }
        // })
        this.setState((state,props)=>{
            return({
                    info:{
                        ...this.state.info,
                        age:state.info.age+1
                    }
            })
        })
        this.setState((state,props)=>({
            info:{
                ...this.state.info,
                age:state.info.age+1
            }
        }))

    }
    componentDidMount(){
        this.changeInfo();
        this.addAge();
    }
    render(){
        let {info,name} = this.state;
        return(
            <div>
                <h3>state</h3>
                名字是:{this.state.name}<br/>
                名字是:{info.name}<br/>
                年龄是:{info.age}<br/>
            </div>
        )
    }
}



export default View;