当前位置: 首页 > 面试题库 >

为什么Async Await与React setState一起使用?

韩玉石
2023-03-14
问题内容

我在ReactJS项目中一直在使用babel的async await。我发现可以方便地与React
setState一起使用,我想更好地理解它。考虑以下代码:

handleChange = (e) => {
  this.setState({[e.target.name]: e.target.value})
  console.log('synchronous code')
}

changeAndValidate = async (e) => {
  await this.handleChange(e)
  console.log('asynchronous validation code')
}

componentDidUpdate() {
  console.log('updated component')    
}

我的意图是让异步验证代码在组件更新后运行。而且有效!生成的控制台日志显示:

synchronous code
updated component
asynchronous validation code

验证代码仅在handleChange更新状态并呈现新状态后运行。

通常要在状态更新后运行代码,您必须在this.setState之后使用回调。这意味着,如果要在handleChange之后运行任何内容,则必须为其提供回调参数,然后将其传递给setState。不漂亮。但是在代码示例中,等待状态以某种方式等待await知道该handleChange已完成…但是我认为等待仅与promise一起使用,并等待一个promise解析后再继续。handleChange中没有承诺,也没有解决方案。它如何知道要等待什么?

这似乎意味着setState是异步运行的,而await以某种方式知道它何时完成。也许setState在内部使用诺言?

版本:

反应:“ ^ 15.4.2”

babel-core:“ ^ 6.26.0”

babel-preset-env:“ ^ 1.6.0”,

babel-preset-react:“ ^ 6.24.1”,

babel-preset-stage-0:“ ^ 6.24.1”

babel-plugin-system-import-transformer:“ ^ 3.1.0”,

babel-plugin-transform-decorators-legacy:“ ^ 1.3.4”,

babel-plugin-transform-runtime:“ ^ 6.23.0”


问题答案:

我尽力简化并补充了戴文的答案,因此您可以更好地了解这里的实际情况:

  1. 将await 放在 this.handleChange的 前面,这将 安排 其余 changeAndValidate 函数的执行,仅在 await 解析 其右侧指定的值(在本例中为 this.handleChange 返回的值)时 运行。
  2. *在 *await 右边的 this.handleChange 执行

2.1。 setState 运行其更新程序,但由于 setState 不保证立即进行更新,因此有可能将更新安排在以后的时间进行
(无论是立即更新还是在以后的某个时间点,重要的是已计划好了)

2.2。console.log(’synchronous code’)运行…

2.3。 this.handleChange 然后退出,返回 未定义
(返回undefined,因为除非明确指定,否则函数返回undefined)

  1. await 然后接受这个 未定义的, 并且因为它不是一个承诺,所以使用 Promise.resolve(undefined) 将其转换为一个已解决的承诺,并等待它-它不会立即可用,因为在幕后它被传递给异步的 .then 方法:

“传递给promise的回调将在当前JavaScript事件循环运行完成之前永远不会被调用”

3.1。这意味着将 undefined 放置在 事件队列 的后面(这意味着它现在在事件队列的setState更新程序之后…)

  1. 事件循环 最终到达并获取我们的 setState 更新,该更新现在执行…

  2. 事件循环 到达并获取 undefined ,其结果为 undefined (如果需要,我们可以存储此值,因此在await前面通常使用= =来存储已解析的结果)

5.1。 Promise.resolve() 现在完成,这意味着 await 不再受影响,因此该函数的其余部分可以恢复

  1. 您的 验证 码运行


 类似资料:
  • 问题内容: 我已经在端口8080(默认)下启动并测试了Tomcat。现在,我将连接器端口更改为80,然后重新启动了Tomcat,在最小的Debian 6.0安装中没有任何显示。现在,这里的窍门在哪里? 问题答案: 转到/ etc / default / tomcat6并更改为

  • 问题内容: 在下面的代码中,我试图使h1元素具有最高利润。当我在css中将位置设置为inline时,未显示上边距。但是,当我将其更改为inline-block时,它确实可以。我想知道是否有人可以解释为什么会这样。谢谢。 这是我的HTML: 这是CSS 问题答案: CSS2规范的9.2.4节规定: inline-block 此值使元素生成一个 内联级块容器 。内联块的内部被格式化为块框,元素本身被格

  • 问题内容: 我正在使用ApplicationTestCase测试一个Android应用程序。我想模拟我的AsyncTasks之一(示例简化为显示问题): 因此,为了设置测试,我做了以下工作: 然后,实际测试如下: 但是运行时出现异常: 为什么模拟AsyncTask的技术不起作用? 请注意,在这种简单情况下,删除会导致问题消失,但是对于我的实际测试,我确实需要创建应用程序。 问题答案: AsyncT

  • 问题内容: 在下面的代码中,我试图使h1元素具有最高利润。当我在CSS中将位置设置为内联时,没有显示页边距顶部。但是,当我将其更改为inline-block时,它确实可以。我想知道是否有人可以解释为什么会这样。谢谢。 这是我的HTML: 这是CSS 问题答案: CSS2规范的9.2.4节)规定: inline-block 此值使元素生成一个 内联级块容器 。内联块的内部被格式化为块框,元素本身被格

  • 问题内容: 我已经在端口8080(默认)下启动并测试了Tomcat。现在,我将连接器端口更改为80,并重新启动了Tomcat,在最小的Debian 6.0安装中没有任何显示。现在,这里的窍门在哪里? 问题答案: 转到/ etc / default / tomcat6并更改为

  • 问题内容: 只是一个让我烦恼的快速问题:为什么要集中精力 确实可以 但当显示设置为 谢谢答案 问题答案: 我的理解如下(尽管我很高兴得到纠正)。 内联元素不具有width属性,因此 无法 计算“自动” 。 块元素具有width属性,因此 可以 计算“自动”的宽度。 内联块元素的外部充当内联,但内部充当块。这样,宽度集的作用类似于内联元素中单词的宽度。