为什么reactjs Async 中的setState 是Async 而不是Sync?

IT技术 javascript multithreading asynchronous reactjs
2021-01-11 02:21:17

我刚刚发现this.setState()在任何组件中的 react函数都是异步的,或者在调用它的函数完成后被调用。

现在我搜索并找到了这个博客(setState() State Mutation Operation May Be Synchronous In ReactJS

在这里,他发现,setState这取决于如何状态的变化引发的是异步(当堆栈是空的称呼)或同步(称为尽快调用)。

现在这两件事很难消化

  1. 在博客中,setState函数是函数内部调用的updateState,但是触发updateState函数的不是被调用函数知道的。
  2. 为什么他们会setState异步的JS是单线程的语言,这样的setState不是的WebAPI或服务器调用,这样,必须只对JS的线程中完成的。他们这样做是为了使重新渲染不会停止所有事件侦听器和其他东西,还是存在其他一些设计问题。
6个回答

你可以调用一个函数的状态值已经更新后:

this.setState({foo: 'bar'}, () => { 
    // Do something here. 
});

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

代替:

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

只需这样做:

this.setState({
    foo: "one",
    bar: "two"
});
是的,没关系,我们有一个可以使用的回调函数,但这不是问题。
2021-03-27 02:21:17
你可能会有所帮助
2021-03-27 02:21:17
希望它会帮助其他人如何偶然发现这个问题。
2021-04-09 02:21:17

1)setState动作是异步的,并且被批处理以提高性能。的文档中对此进行了解释setState

setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。无法保证对 setState 调用的同步操作,并且可能会批量调用以提高性能。


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

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

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

如果您需要在调用 setState 后确保事件的顺序,您可以传递一个回调函数。 this.setState({ something: true }, () => console.log(this.state))
2021-03-11 02:21:17
为什么不允许设置一个选项来使功能异步或同步?这将是一个有用的功能
2021-03-18 02:21:17
谢谢@Sachin 的解释。但是,我仍然有疑问,它可以像博客解释的那样同步吗?
2021-03-31 02:21:17
React 中的另一个愚蠢的设计决定。使状态更新同步,渲染异步。您可以批量渲染,但我希望能够将一些东西设置为状态变量的原始状态,而不必处理竞争条件。
2021-04-05 02:21:17
显然,我不是 React 团队的成员,但在我看来,使状态更新异步的一个原因是浏览器是单线程的。同步操作可能会使 UI 无响应,并且不适合 UI。
2021-04-08 02:21:17

我知道这个问题很老,但长期以来它一直给许多 reactjs 用户带来很多困惑,包括我。最近 Dan Abramov(来自 react 团队)刚刚写了一篇很好的解释,解释了为什么setStateasync的本质

https://github.com/facebook/react/issues/11527#issuecomment-360199710

setState是异步的,在 Dan Abramov 的链接解释中有几个很好的理由。这并不意味着它总是异步的——它主要意味着你不能依赖它是同步的ReactJS 会考虑您正在更改状态的场景中的许多变量,以决定何时state实际更新和重新渲染您的组件。
一个简单的例子来证明这一点,如果你调用setState作为对用户操作的react,那么它state可能会立即更新(尽管你不能指望它),所以用户不会感觉到任何延迟,但如果你打电话setState 响应 ajax 调用响应或其他一些不是由用户触发的事件,那么状态可能会稍微延迟更新,因为用户不会真正感受到这种延迟,它将通过等待来提高性能一起批处理多个状态更新并减少重新渲染 DOM 的次数。

你还没有将任何答案标记为正确的答案。人们正在发布如何解决它。不是所问问题的答案。这篇文章看起来不错。
2021-03-10 02:21:17
@Anup 答案比“异步”或“同步”要复杂一些。它应该始终被视为“异步”,但在某些情况下可能会表现为“同步”。我希望我能给你一些启发。
2021-03-25 02:21:17

这里的好文章 https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md

// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3

Solution
this.setState((prevState, props) => ({
  count: prevState.count + props.increment
}));

或通过回调 this.setState ({.....},callback)

https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b

您可以使用以下包装进行同步调用

this.setState((state =>{
  return{
    something
  }
})

传递回调不会改变setState异步的事实
2021-03-22 02:21:17
被低估的答案
2021-04-05 02:21:17