最近在做项目的时候发现了原来react的三大核心属性,原来还有自己不知道的很多细节,特此记录一下。
1.什么是state?
状态驱动视图的更新,这是我们使用state的核心观念,为了让数据能够响应式的处理,我们在react中用到的是state这个属性,区别于vue中的data数据,我们在修改state的时候要通过setState方法来进行修改,不然在会出现数据无法响应式的现象。
2.怎么用state?
在类式组件中,我们可以在构造函数中初始化state,由于一个组件中有可能有很多状态需要维护,所以state很自然的是类的格式,同时有时候我们的构造器是非必须的,我们直接赋值给构造函数外的state属性:
而后我们要进行状态修改就要通过setState来进行了。
3.setState的使用方法?
(1). setState(stateChange, [callback])------对象式的setState
1.stateChange为状态改变对象(该对象可以体现出状态的更改)
2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
(2). setState(updater, [callback])------函数式的setState
1.updater为返回stateChange对象的函数。
2.updater可以接收到state和props。
4.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
总结:
1.对象式的setState是函数式的setState的简写方式(语法糖)
2.使用原则:
(1).如果新状态不依赖于原状态 ===> 使用对象方式
(2).如果新状态依赖于原状态 ===> 使用函数方式
(3).如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取
4.state的默认行为-----状态合并
无论是对象类型还是函数类型,它都会进行状态的合并,所有状态合并后在进行一次性dom更新,我们来看下面的代码
我们会发现点击之后,每次count的值只会加一,难道只有一次setState生效了吗?其实都生效了,只是在setState之前,会进行一次合并,执行的是最后合并的代码。在看看下面的代码:
点一次加了2,说明两次都执行了,并没有状态的合并,注意这里用来改变state的是箭头函数的参数,它代表前一个值,对比下图:
这里我们没有用前一个state来更新当前的转态,所以还是只加了一次,原因就是获取这样获取的时候,还没更新,那状态改变是异步还是同步的呢?
5.setState到底是异步的还是同步的?
我们直接上代码:
很明显这是异步的。那我们要获得更新后的state怎么办?前面的知识告诉我们,要用setState的第二个回调:
很顺利,我们拿到了setState之后的值,还有没别的办法?我们再看
???什么鬼,这里的又变成同步的了。那到底是啥情况?我们先说结论:
同步还是异步是取决于setState的调用环境!
- 如果 setState 在 React 能够控制的范围被调用,它就是异步的。
比如合成事件处理函数, 生命周期函数, 此时会进行批量更新, 也就是将状态合并后再进行 DOM 更新。
- 如果 setState 在原生 JavaScript 控制的范围被调用,它就是同步的。
比如原生事件处理函数中, 定时器回调函数中, Ajax 回调函数中, 此时 setState 被调用后会立即更新 DOM 。
那这是什么原因呢?
原来我们看到的这样的异步,其实是批量更新模式搞得鬼!为了提高性能,减少真实dom渲染的次数,只要是在react可控的范围内,出于性能的考虑,就会开启这个模式。否则一有setState就进行re-render开销将会非常的大!开启该模式后,每一个setState会被塞入到对列中,等有机会的时候,把state的结果进行合并,一次进行更新,对于同名的state就会以最后一次为准。
6.那既然没有该模式性能那么差,我们有时候又要在react不可控的地方使用setState怎么办?
这时候我们就要引入我们的unstable_batchedUpdates了。他是在react-dom中。我们直接看代码:
显然批量更新模式又开启了!
小小总结一下
- 数据需要响应式我们想到state.
- 更新state我们只能通过setState,该函数接受两个参数,参数一是新的state,这个操作是合并不是覆盖,可以有对象形式和函数形式两种,要获取上一个状态时候我们就要用回调函数的形式,它接受的参数就有上一次的state,setState的第二个参数是一个回调函数,帮助我们在其更新完成之后获取state的值。
- setState到底是异步还是同步?首先其本身的调用就是普通函数的调用肯定是同步的,但是背后的操作是异步还是同步就取决于调用的环境了,如果在react可控的范围下,其会开启批量更新模式,此时是异步的,而在其他环境下没有开启就是同步的。
- 在非react可控的环境下,我们可以通过unstable_batchedUpdates来开启批量更新模式!