reactjs - 为什么 Async Await 可以与 React setState 配合使用?

标签 reactjs async-await babeljs

我一直在我的 ReactJS 项目中使用 async wait 和 babel 。我发现了 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 已完成...但我认为await 只能与promise 一起使用,并在继续之前等待promise 解决。在handleChange 中没有 promise 也没有解决方案...它如何知道要等待什么?

这似乎意味着 setState 是异步运行的,并且 wait 以某种方式知道它何时完成。也许 setState 在内部使用了 Promise?

版本:

react :“^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”

最佳答案

我尽力简化和补充 Davin 的答案,以便您可以更好地了解这里实际发生的情况:

<小时/>
  1. await 放在 this.handleChange 前面,这将安排执行 changeAndValidate 的其余部分> 函数仅在 await 解析 其右侧指定的值时运行,在本例中为 this.handleChange 返回的值
  2. this.handleChange,在await右侧,执行:

    2.1。 setState 运行其更新程序,但由于 setState 不保证立即更新,因此可能会安排稍后进行更新(这并不重要如果是立即发生或稍后发生,重要的是它是已安排的)

    2.2。 console.log('同步代码') 运行...

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

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

“Callbacks passed into a promise will never be called before the completion of the current run of the JavaScript event loop”

3.1。这意味着未定义将被放置到事件队列的后面(这意味着它现在位于事件队列中我们的setState更新程序后面......)

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

  • 事件循环到达并获取未定义,其计算结果为未定义(如果我们想要的话,我们可以存储它,因此通常在await前面使用=来存储解析的结果)

    5.1。 Promise.resolve() 现已完成,这意味着 await 不再有效,因此函数的其余部分可以恢复

  • 您的验证代码运行
  • 关于reactjs - 为什么 Async Await 可以与 React setState 配合使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47019199/

    相关文章:

    javascript - 在 Browserslist 中为 Babel 添加 "not dead"会产生不同的结果,即使浏览器是相同的?

    javascript - browserify - 排除代码块?

    c# - 等待抽象函数完成 c#

    javascript - ES6 生成器——它们真的是异步/等待的替代品吗?

    c# - 返回已完成任务的异步方法出乎意料地慢

    node.js - 如何在es2015中导入rethinkdbdash

    reactjs - React Hook useReducer 总是运行两次

    javascript - 在 React JS 中使用键显示列表中项目的正确方法是什么?

    reactjs - 在 react 中基于 Prop 引用图像

    javascript - 使用 babel-polyfill 加载哪些 polyfill