组件分为函数组件和类组件,在
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的最佳实践
- 把所有的setState当作是
异步的
- 永远
不要信任setState调用之后的状态
- 如果要使用改变之后的状态,需要使用
回调函数
(setState的第二个参数) - 如果
新的状态要根据之前的状态进行运算
,使用函数的方式
改变状态(setState的第一个函数)