【重点】setState
- 不可变值
- 可能是异步更新
- 可能会被合并
state 要在构造函数中定义
- 函数组件(后面会讲),默认没有 state
不能直接修改 state ,使用 不可变值
- 不能直接修改 state,需要使用setState。也不能提前修改state再使用setState,在setState中什么使用需要state再进行修改。
- 简单例子:修改state中的值类型(原因:shouldComponentUpdate中具体阐述)
修改state中的引用类型
- 原则:在setState中使用的方法都不能改变state中的原数组/对象(比如数组的push pop splice都不能使用),或者在setState前先拷贝数组/对象来进行操作。
- 【数组】state中存放 数组时,需要注意不能直接对
this.state.list
进行 push pop splice 等会直接改变原数组(state中数据)的操作,这样违反不可变值。需要做复杂操作时,可先拷贝出来再进行操作。(ES6 filter-数组过滤方法) - 【对象】巧用assign方法将state中对象放在参数2,则可不改变state中原对象。
setState 可能是异步/同步更新
- 能命中batchUpdate机制的入口(即:react可以“管理”的入口)中使用 setState 是异步:JSX中、合成事件中
- 不能命中batchUpdate机制的入口(即:react“管不到”的入口)中使用 setState 是同步:setTimeout setInterval等、自定义的DOM事件(注意搭配componentWillUnmount()中使用removeEventListener()解绑事件,react合成事件统一绑定在document上,就不需要频繁解绑了)
JSX 中使用 setState 是异步
- 直接在JSX中使用 setState 是异步的:
- 但是setState的参数2(回调函数)中可获取到最新state
JSX合成事件 中使用 setState 是异步
- 此处无例子
- 注意:onclick是DOM事件,通过addEventListener绑定的click事件是“自定义的 DOM 事件”,JSX中的onClick是 合成事件
原生DOM事件 中使用 setState 是同步
- 自定义的 DOM 事件中 setState 是同步的(即原生DOM事件中是同步的,只要html中能正常跑起来的绑定方法就是原生DOM事件):在body上绑定自定义的click事件,在该DOM事件中setState 是同步的
- 注意:“自定义的 DOM 事件”的概念,onclick是DOM事件,通过addEventListener绑定的click事件是“自定义的 DOM 事件”,JSX中的onClick是 合成事件
setTimeout 中使用 setState 是同步
setTimeout 中 setState 是同步的:
setState异步更新前合并/不合并
setState中传入 对象 会被合并
state 异步更新时,setState中传入对象,会被合并,执行结果只一次,点击一次“累加”按钮的执行结果是 +1:一样用点击按钮累加数字作为例子,点击事件的事件函数increase中设置3次setState,由于这里是异步的setState,所以点击按钮时,系统会发现setState3次都是一样的修改,最后会被合并为1次(即每次点击都只+1不会+3 )
setState中传入 函数 不合并
- state 异步更新时,setState中传入函数,不会被合并。点击一次“累加”按钮的执行结果是 +3:
- 函数是无法合并的,所以三个函数都会生效
补充:setState()的两个参数
- 注意:setState中推荐传入函数
- setState()的参数1(回调函数)可以接受两个参数:prevState, props(),第一个参数是原始state,等同于
this.state
,第二个参数是父组件传递的属性。(参考) - setState()的参数2(回调函数)内可获取state的最新值,在这个函数内可解决由于setState是异步的,有些事件我们需要等setState更新完才触发的问题(参考)
组件生命周期
- React 组件生命周期图示
- 更多可参考博客“React高级内容(2)”