一、组件state

1,设计合适的state

state必须能代表一个组件UI呈现的完整状态集,代表一个组件UI呈现的最小状态集。

state必须能代表一个组件UI呈现的完整状态集又可以分成两类数据:用作渲染组件时使用到的数据的来源,用作组件UI展现形式的判断依据:

class Hello extends Component {
    constructor(props) {
        super(props);
        this.state = {
            user: 'react', //用作渲染组件时使用到的数据的来源
            display: true //用作组件UI展现形式的判断依据
        }
    }
    render() {
        return (
            <div>
                {
                    this.state.display ? <h1>{this.state.user}</h1> : <></>
                }
            </div>
        )
    }
}
export default Hello;

普通属性:

在es6中,可以使用this.属性名定义一个class的属性,也可以说属性是直接挂载在this下的一个变量。因此,state和props实际上也是组件的属性,只不过是react在Component class中预定义好的属性。除了state和props以外的其他组件属性称为组件的普通属性。

class Hello extends Component {
    constructor(props) {
        super(props);
        this.timer = null; //普通属性
        this.state = {
            date: new Date()
        }
        this.updateDate = this.updateDate.bind(this);
    }
    componentDidMount(){
        this.timer = setInterval(this.updateDate, 1000);
    }
    componentWillUnmount(){
        clearInterval(this.timer);
    }
    updateDate(){
        this.setState({
            date: new Date()
        })
    }
    render() {
        return (
            <div>
                <h1>{this.state.date.toString()}</h1>
            </div>
        )
    }
}
export default Hello;

组件中用到的一个变量是否应该作为state可以通过下面4条依据判断:

  • 这个变量是否通过props从父组件中获取?如果是,那么它不是一个状态
  • 这个变量是否在生命周期中都保持不变?如果是,那么它不是一个状态
  • 这个变量是否可以通过其他状态(state)或者属性(props)计算得到?如果是,那么它不是一个状态
  • 这个变量是否在组件的render方法中使用?如果不是,那么它不是一个状态,这种情况更适合定义为组件的一个普通属性

2,正确修改state

①不能直接修改state,需要使用setState()

②state的更新是异步的

React会将多次setState的状态合并成一次状态修改,不能依赖当前的state计算下一个state(props也是异步的)。

例如:连续两次点击加入购物车,实际数量只会加1,在React合并多次修改为1次的情况下,相当于执行了:

Object.assign(
    previousState,
    {quantity: this.state.quantity + 1},
    {quantity: this.state.quantity + 1}
)

这种情况下,可以使用另一个接收一个函数作为参数的setState,这个函数有两个参数,第一个是当前修改后的最新状态的前一个状态preState,第二个参数是当前最新的属性props:

this.setState((preState,props) => ({
    quantity: preState.quantity + 1;
}))

③state的更新是一个合并的过程

④state与不可变对象

直接修改state,组件不会render;state包含的所有状态都应该是不可变对象,当state中某个状态发生变化时,应该重新创建这个状态对象,而不是直接修改原来的状态。创建新的状态有以下三种方法:

  • 状态的类型是不可变类型(数字、字符串、布尔值、null、undefined):因为状态是不可变类型,所以直接赋一个新值即可
  • 状态的类型是数组:可以使用数组的concat或者es6的扩展语法,slice方法、filter方法。不能使用push、pop、shift、unshift、splice等方法修改数组类型的状态,因为这些方法会在原数组基础上修改。
this.setState((preState) => ({
    arr: [...preState.arr,'react'];
}))
this.setState((preState) => ({
    arr: preState.arr.concat(['react'])
}))
  • 状态的类型是普通对象(不包含字符串、数组):使用ES6的Object.assgin方法或者对象扩展语法
posted on 2022-10-25 14:40  Zoie_ting  阅读(61)  评论(0编辑  收藏  举报