React基础篇之state


前言

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
类组件 函数组件
有状态组件 无状态组件
容器组件 展示组件

尽可能使用状态提升原则,将需要的状态提取到父组件当中,而其他的组件使用无状态组件编写
==尽可能使用无状态组件,尽少的使用状态组件==
因为无状态组件会使应用变得简单可维护,而且数据流也会简单
在必须使用状态的时候编写状态组件,在组件内部使用无状态组件


文章作者: 庄荣健
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 庄荣健 !
  目录