03-状态

7/24/2023

# 一,状态

# 1,状态在类组件中的使用

前面我们定义的数据,都是普通变量,并不是状态,现在我们开始学习state。

安装一个react的调试插件,如下:

1675135092169

使用之,如下:

1675135174025

代码如下:

1675135277171

浏览器中效果如下 :

1675135289725

尝试直接修改状态,如下:

1675135642566

当我们点击时,报错了,如下:

1675135677592

打印出this是und,如下:

1675135745445

此时,就需要显示绑定this,如下:

1675135831388

绑定this后,我们再去修改状态,如下:

1675135909742

直接修改状态,不推荐,因为修改状态的目的还需要让模板刷新,有个专属API,叫setState,是专门来用来修改状态的,如下 :

1675136135787

我们现在的想法是让它每一次都+1,如下:

1675136432517

虽然++在前是OK的,但是不推荐,原因是修改了两次num,一次是直接修改,一次是间接修改。最好的处理方法如下:

1675136574325

this.setState是异步的,在React18中,永远是异步的,在React18之前,有可能是同步,有可能是异步,测试如下:

1675136725480

上面的修改状态的写法,还不是很优雅,比较优雅的写法,如下:

1675136967494

上在的写法,可以简写,如下:

1675137130768

浏览器测试如下:

1675137155379

this.setState有两种写法:

  • this.setState({}, callback) 在修改状态时,当新值与旧值无关时,推荐使用这种写法,callback表示当状态修改后,自动执行,当状态修完后,有一些业务逻辑放到callback中。
  • this.setState((state, props)=>({}), callback) 当新值与旧值有关时,新值由旧值计算而来,形参state永远表示旧值,建议使用这种写法。callback表示当状态修改后,自动执行,当状态修完后,有一些业务逻辑放到callback中。

上面我们讲了,在类组件中如何定义状态,如何使用状态,如何修改状态。

# 2,修改状态的同步和异步问题

在React18之前,React16和React17,this.setState在合成事件中,是异步的。在宏任务(定时器),Promise.then中是同步的。所谓的React合成事件是指on*系列事件,生命周期函数。

在React18中,this.setState任务时候都是异步的。代码如下:

1677048889060

1677049089120

总结:

  • 在React18之前,setState写在宏任务中,或Promise.then中,它是同步的。
  • 在React18之前,setSteate写在合成事件中,是异步的。
  • 在React18中,不管setState写在哪里,永远都是异步的。

在V18中,setState一定是异步的,如下:

1675149175555

如果放在定时器,如下:

1675149309248

你要想看一下修改后状态的结果,如下:

1675149447581

看一下如下代码,分析结果,如下:

1675149862919

为什么是V18版本中,把this.setState设计成异步的?

答:为了性能优化。在V18中,无论this.setState在哪里,都是异步的,这种特性,叫”并发模式“

this.setState会自动合并,如下:

1675150126541

看再如下代码:

1675150385592

# 3,初识事件绑定

看如下事件绑定:

1675150622045

上面的写法,不完美,因为在监听器中不能获取到this。this是und。解决办法有两种:

  • 利用ES5中的bind中手动绑定this
  • 利用ES6中的箭头函数自动绑定this

ES5绑定代码如下:

1675150797705

浏览器测试如下:

1675150777292

使用ES6中的箭头函数自动绑定this,代码如下:

1675150898274

浏览器中测试如下:

1675150932666

想获取事件对象,如下:

1675150995435

# 4,状态在函数组件中的使用

函数组件中是不能定义状态,但是配合hook可以定义状态,hook类似于vue3中的组合式API,在React16.8中就有了,React16.8有三四年,hook也有三四年,只不过,最近两年hook才火起来了。

直接上代码,如下:

1675152569211

看下面的写法,有没有问题:

1675152874814

setNum是同步还是异步,如下:

1675152972870

setNum是同步还是异步,在不同的版本中是不一样的,总结如下:

  • 在V18之前,在合成事件中是异步的,在宏任务和promise.then中是同步的。
  • 在V18中,无论在哪里都是异步的。

setNum中,是没有callback。setNum还有一种写法,如下:

1675153198929

Last Updated: 2/27/2023, 10:05:39 PM