组件分为函数组件和类组件,在hooks 出来之前,只有类组件才有状态,现在不管函数组件和类组件,都是含有状态的。这里只讨论类组件的状态
含义以及意义
** 含义**
组件的状态,其实就是组件中的一个属性,这个属性就是state。
import React, { Component } from 'react' // 定义一个状态的接口 interface IState { // 定义一个n,为number 类型 n: number } export default class TestState extends Component { // 这个语法是esnext中的,在react中是可以使用的,可以使用babel来进行转译 state:IState = { n: 100 } render() { // 获取状态值 console.log(this.state.n); return ( <div> 状态值{this.state.n} </div> ) } }
结果
组件为什么需要状态(state)
我们都知道,每个组件时一个独立的ui单元,包含行为(js),样式(css),结构(html)。每个组件里面可以传递参数,但是传递的参数是不能修改的(详情查看)。如果在组件内部修改修改参数,那么就需要使用到组件状态state
- 组件状态(state):组件可以自行维护的数据
- 组件状态(state)仅在类组件中有效
- 状态(state),本质上是类组件的一个属性,是一个对象
状态初始化
两种初始化的方式:构造函数声明,使用esnext语法进行声明
构造函数声明
import React, { Component } from 'react' // 定义一个状态的接口 interface IState { // 定义一个n,为number 类型 n: number } export default class TestState extends Component<{}, IState> { // 这里的IState 对状态进行声明 constructor(props:{}){ super(props); // 此处进行赋值 this.state = { n: 100 } } render() { // 获取状态值 console.log(this.state.n); return ( <div> 状态值{this.state.n} </div> ) } }
结果
esnext 语法进行声明
在上述代码,含义中的举例就是通过esnext 的方式进行声明的.
查看
状态变化
1.不能直接改变状态:因为React无法监控到状态发生了变化
2.必须使用this.setState({})改变状态
例如:
import React, { Component } from 'react' // 定义一个状态的接口 interface IState { // 定义一个n,为number 类型 n: number } export default class TestState extends Component<{}, IState> { constructor(props:{}){ super(props); this.state = { n: 100 } // 这里使用计时器,来改变里面的值 setInterval(() => { this.setState({ n: this.state.n - 1 }) },1000) } render() { return ( <div> 状态值{this.state.n} </div> ) } }
结果
3.一旦调用了this.setState,会导致当前组件重新渲染,当前组件里面的其他组件也会重新着渲染。
- 上面的计时器中,每次改变,页面上的渲染结果也是跟着改变的可以说明问题
- 如果在render里面写了this.setState({}),会导致内存溢出也可以说明问题:
state 注意事项
state与props的区别
- props:该数据是由组件的使用者传递的数据,所有权不属于组件自身,因此组件无法改变该数组
- state:该数组是由组件自身创建的,所有权属于组件自身,因此组件有权改变该数据
setState,它对状态的改变,可能是异步的
代码修改如下:
当我点击按钮的时候,页面的数据是会发生改变的,这个和我们的html 是一样的,页面的js事件来改变页面渲染的值。但是结果却是如下:(页面上的值改变了,但是当前方法里面的值却是没有改变的)
结论: 如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步
获取state修改后的数据
通过setState的第二个参数
通过setState的第二个参数获取修改后的值
change方法进行修改:
结果
思路拓展
如果我想要连续的修改state的某个值,那么代码将会是这样的:
代码的执行的结果是没有问题的:
解决办法
我们通过上面的setState的声明中可以看到,第一个参数是可以使用一个函数的,如果遇到某个事件中,需要同步调用多次,需要使用函数的方式得到最新状态
修改change方法:
结果
分析:为啥render只是执行一次?
个人理解:在同一个事件或者函数中,React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对state进行改变,然后触发render)
state的最佳实践
1.把所有的setState当作是异步的
2.永远不要信任setState调用之后的状态
3.如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)
4.如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)