为什么 async 函数在 this.setState 之后起作用?

Why do the async function works after this.setState?

假设我有以下代码;

ComponentDidMount(){
  const res = fetch(smth) 

  this.setState({data: res}) // first setState

  const res2 = fetch(another)

  this.setState({data2: res2}) // second setState
}

问题是 setState 都可以。我在想第一个 setState 调用 render() 并且组件重新加载,第一个 setState 之后的代码将不起作用

为什么?

根据 docs:

componentDidMount() is invoked immediately after a component is mounted (inserted into the tree)....... You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state.

这意味着 "componentDidMount()" 中的所有代码都在用户看到 render() 中的结果之前被调用。

这不是 set setState 的工作方式。

如果你想保证在 setState 之后调用某些东西,你应该试试这个:

async componentDidMount () {
   const res = await fetch(smth);

   this.setState({data: res}, async () => {
      // put the second fetch here
      const res2 = await fetch(another);

      this.setState({data2: res2});
   });
}

我将尝试解释为什么它是异步的以及如何将多个状态包装在一起,

1) setState 操作是异步的,并且是批处理的以提高性能。 setState.

的文档对此进行了解释

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

2) 为什么他们要让 setState 异步,因为 JS 是单线程语言,而这个 setState 不是 WebAPI 或服务器调用?

这是因为 setState 改变了状态并导致重新渲染。这可能是一项昂贵的操作,使其同步可能会使浏览器无响应。

因此 setState 调用是异步和批处理的,以获得更好的 UI 体验和性能。

一个简单的例子来证明这一点,如果你调用 setState 作为对用户操作的反应,那么状态可能会立即更新(虽然,同样,你不能指望它),所以用户不会感觉到任何延迟,但是如果您调用 setState 来响应 ajax 调用响应或其他非用户触发的事件,则状态可能会稍微延迟更新,因为用户不会真正感受到这种延迟,它会通过等待将多个状态更新批处理在一起并减少 DOM 次重新渲染来提高性能。

如果您有很多状态要同时更新,请将它们全部分组在同一个 setState:

  this.setState({foo: "one"}, () => {
     // do something
    this.setState({bar: "two"});
});

所以你上面的代码应该类似于,

   async ComponentDidMount() {
   const res = await fetch(smth);

   this.setState({data: res}, async () => {
      //do something more.... 
      const res2 = await fetch(another);

      //setState again .....
      this.setState({data2: res2});
   });
}