前言
React的核心思想是组件化的思想,应用由组件搭建而成,组件中最重要的概念就是state(状态)
怎样定义是否需要一个state
- 是否通过props从父组件获取,是就需要
- 是否可以通过其他state和props计算得到,不是就需要
- 是否在render方法中使用,是就需要
定义与使用
类中定义 constructor
在其中写this.state,所有状态都放在里面
constructor(props) {
super(props);
this.state = {
count:0
}
}
使用
this.state.count
修改state的值
在constructor之外只能使用setState方法修改state的值
handleDecrease = ()=>{
this.setState({
count:this.state.count - 1
})
}
在constructor之内则不能这么写,不然会报错,只能用this.state赋初始值
注意点
- setState的处理过程是异步的而不是同步的,调用了setState之后组件的state并不会立刻改变,不要依赖当前state去计算另外一个state,因为可能拿不到值
- state的更新是一个浅合并的过程,当一个state中有很多个属性的时候,在某一个时间处理函数中只需要对相应的属性做修改就可以了
创建新的状态
状态类型
- 值类型(数字、字符串、布尔值、null、undefined)
- 数组类型
- 对象
当状态类型为值类型时可以直接使用setState方法赋值
this.setState({
count:99,
name:'数字电视',
show:true
})
当状态类型为数组类型时建议先用concat或者…拷贝之后再使用setState方法赋值
//concat
const _books = this.state.books.concat('new book')
this.setState({
books:_books
})
//...
const _books = [...this.state.books,'new book']
this.setState({
books:_books
})
当状态类型为对象时建议先用Object.assign或者…拷贝之后再使用setState方法赋值
//Object.assign
item = {
id: 1,
name: 'sony tv',
price: 7000
}
const _item = Object.assign({},this.state.item,{price:9000})
this.setState({
item:_item
})
//...
item = {
id: 1,
name: 'sony tv',
price: 7000
}
const _item = {...this.state.item,price:9000}
this.setState({
item:_item
})
state和props的区别
| state | props |
|---|---|
| 可变的 | 在组件内部不可变 |
| 只可以在组件内部初始化和修改,外部不可访问和修改 | 父组件中传入 |
| 交互或其他UI造成的数据更新(通常情况下state变化时组件会重新渲染) | 从上而下的简单的数据流 |
state和props的联系
- state可以通过props传入子组件
- 传入的props初始化state
要点
- 通过条件判断优化渲染
- 使用不可变数据
- 状态提升
- 使用无状态组件
状态更新扩展
默认情况下,只要有更新传入props和state,无论传入的props和state的值相较之前是否有变化,都会触发render重新渲染(这里的重新渲染指的是虚拟dom的渲染,而非实际dom的重绘)
想要更新props和state值时不触发重新渲染有以下两种方法
使用shouldComponentUpdate方法,直接和render写平级就行,只需要写函数,不需要写调用(这个应该是react自带的方法)
shouldComponentUpdate(nextProps, nextState) {
if (this.props.id === nextProps.id) return false;
return true;
};
使用PureComponent 代替Component
//引入
import React, { PureComponent } from "react";
//使用
class ListItem extends PureComponent {}
为何使用不可变数据
当使用可变数据时,PureComponent中可能无法更新视图
解决方法是将可变数据变为不可变数据,可以使用concat来做
const _list = this.state.listData.concat([])
在实际项目中尽可能使用PureComponent去优化组件
使用不可变数据可以避免引用带来的副作用,使整个程序的数据变得易于管理
单一数据源
应用状态之间相互独立虽然使用起来很方便,但是一旦应用变得复杂起来时会产生极大的混乱,遵从单一数据源的原则就能很好的解决问题(所有相同的子组件应该有一个主状态,然后使用该状态以props的形式传递给子组件)
状态提升
状态提升主要用来处理父组件和组件之间的状态传递,他可以让我们的数据流是自顶向下单向流动的形式
当子组件需要控制同一个数据源的时候,需要将整个数据提升到他们共同的数据源当中,然后再通过父组件赋值的方式赋给子组件,并由父组件对数据进行统一的管理和存储
有状态组件和无状态组件
函数组件的另一个名称就是无状态组件,顾名思义,无状态组件就是组件中没有state状态
类组件就是有状态组件
| stateful | stateless |
|---|---|
| 类组件 | 函数组件 |
| 有状态组件 | 无状态组件 |
| 容器组件 | 展示组件 |
尽可能使用状态提升原则,将需要的状态提取到父组件当中,而其他的组件使用无状态组件编写
==尽可能使用无状态组件,尽少的使用状态组件==
因为无状态组件会使应用变得简单可维护,而且数据流也会简单
在必须使用状态的时候编写状态组件,在组件内部使用无状态组件