Javascript Reactjs 中是否有 setState() 的同步替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42018342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a synchronous alternative of setState() in Reactjs
提问by shubham agrawal
According to the explaination in the docs:
根据文档中的解释:
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.
setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。
无法保证对 setState 调用的同步操作,并且可能会批量调用以提高性能。
So since setState()is asyncronous and there is no guarantee about its synchronous performance. Is there an alternative of setState()that is syncronous.
所以因为setState()是异步的,所以不能保证它的同步性能。有没有替代方案setState()是同步的。
For example
例如
//initial value of cnt:0
this.setState({cnt:this.state.cnt+1})
alert(this.state.cnt); //alert value:0
Since the alertvalue is previous value so what is the alternative that will give alert value:1using setState().
由于该alert值是以前的值,因此alert value:1使用setState().
There are few questions on Stackoverflow which is similar to this question but no where I am able to find the correct answer.
Stackoverflow 上有几个问题与这个问题类似,但我找不到正确的答案。
回答by Oscar
As you have read from the documentation, there is NO sync alternative, reason as described is performance gains.
正如您从文档中读到的,没有同步替代方案,所描述的原因是性能提升。
However I presume you want to perform an action after you have changed your state, you can achieve this via:
但是,我认为您想在更改状态后执行操作,您可以通过以下方式实现:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
x: 1
};
console.log('initial state', this.state);
}
updateState = () => {
console.log('changing state');
this.setState({
x: 2
},() => { console.log('new state', this.state); })
}
render() {
return (
<div>
<button onClick={this.updateState}>Change state</button>
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
回答by ModestLeech
You could wrap setStatein a function returning a promise, and then use this function with the awaitkeyword to cause your code to wait until the state has been applied.
您可以包装setState在一个返回承诺的函数中,然后将此函数与await关键字一起使用,以使您的代码等待直到应用状态。
Personally, I would never do this in real code, instead I would just put the code I wish to execute after the state update in the setStatecallback.
就个人而言,我永远不会在实际代码中执行此操作,而是将我希望在状态更新后执行的代码放入setState回调中。
Nerveless, here is an example.
不用担心,这是一个例子。
class MyComponent extends React.Component {
function setStateSynchronous(stateUpdate) {
return new Promise(resolve => {
this.setState(stateUpdate, () => resolve());
});
}
async function foo() {
// state.count has value of 0
await setStateSynchronous(state => ({count: state.count+1}));
// execution will only resume here once state has been applied
console.log(this.state.count); // output will be 1
}
}
In the foo function, the awaitkeyword causes the code execution to pause until the promise returned by setStateSynchronoushas been resolved, which only happens once the callback passed to setStateis called, which only happens when the state has been applied. So execution only reaches the console.log call once the state update has been applied.
在 foo 函数中,await关键字导致代码执行暂停,直到返回的 promisesetStateSynchronous被解析,这只会在调用传递给的回调setState时发生,只有在应用状态时才会发生。因此,一旦应用了状态更新,执行只会到达 console.log 调用。
docs for async/await:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
async/await 的文档:
https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript /参考/运营商/等待
回答by S.Kiers
If this is required I would suggest using a callback in your setState function (and I also suggest using a functional setState).
如果这是必需的,我建议在您的 setState 函数中使用回调(并且我还建议使用功能性 setState)。
The callback will be called after the state has been updated.
状态更新后将调用回调。
For example, your example would be
例如,你的例子是
//initial value of cnt:0
this.setState(
(state) => ({cnt: state.cnt+1}),
() => { alert(this.state.cnt)}
)
as per documentation here : https://facebook.github.io/react/docs/react-component.html#setstate
根据此处的文档:https: //facebook.github.io/react/docs/react-component.html#setstate
Note: Official docs say, "Generally we recommend using componentDidUpdate() for such logic instead."
注意:官方文档说,“通常我们建议使用 componentDidUpdate() 来代替这种逻辑。”
回答by Jemar Jones
No, there is not. React will update the state when it sees fit, doing things such as batching setStatecalls together for efficiency. It may interest you that you are able to pass a function into setStateinstead, which takes the previous state, so you may choose your new state with good knowledge of the previous one.
不,那里没有。React 会在它认为合适的时候更新状态,做一些事情,比如将setState调用一起批处理以提高效率。您可能会感兴趣的是,您可以将一个函数传入setState,它采用以前的状态,因此您可以在对前一个状态有充分了解的情况下选择新状态。
回答by Hussain Saify
It may sound weird but yes setState can work synchronously in react. How so? This is POC which I've created to demonstrate it.
听起来可能很奇怪,但是 setState 可以在 react 中同步工作。为何如此?这是我创建的 POC 来演示它。
Pasting the only app JS code.
粘贴唯一的应用程序 JS 代码。
Maybe it's possible that I'm missing something but this was actually happening in my application that's when I came to know about this effect.
也许我遗漏了一些东西,但这实际上是在我的应用程序中发生的,那时我才知道这种效果。
Correct me if this kind of behavior is expected in React which I'm unaware of. When there are multiple setState on main thread the setState runs a Batch combining all the setState on the main method. Whereas the Scenario is different when the same things go inside the async Function.
如果我不知道 React 中会出现这种行为,请纠正我。当主线程上有多个 setState 时,setState 会运行一个 Batch 组合主方法上的所有 setState。而当相同的东西进入异步函数时,场景就不同了。
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
}
this.asyncMethod = this.asyncMethod.bind(this);
this.syncMethod = this.syncMethod.bind(this);
}
asyncMethod() {
console.log("*************************")
console.log("This is a async Method ..!!")
this.setState({
counter: this.state.counter + 1
}, () => {
console.log("This is a async Method callback of setState. value of counter is---", this.state.counter);
})
console.log("This is a async Method on main thread. value of counter is---", this.state.counter);
console.log("*************************")
}
syncMethod() {
var that = this;
console.log("*************************")
console.log("This is a sync Method ..!!")
that.setState({counter: "This value will never be seen or printed and render will not be called"});
that.setState({counter: "This is the value which will be seen in render and render will be called"});
setTimeout(() => {
that.setState({counter: "This is part is synchronous. Inside the async function after this render will be called"});
console.log("setTimeout setState");
that.setState({counter: "This is part is aslso synchronous. Inside the async function after this render will be called"});
}, 10)
console.log("This is a sync Method on Main thread. value of counter is---", this.state.counter);
console.log("*************************")
}
render() {
console.log("Render..!!",this.state.counter);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
</header>
<button onClick={this.asyncMethod}>AsyncMethod</button>
<button onClick={this.syncMethod}>SyncMethod</button>
</div>
);
}
}
export default App;
回答by Pulkit Aggarwal
Yes, there is a method with which we can make our synchronous setState. But its performance maybe not good as normally For example, we have
是的,有一种方法可以使我们同步 setState。但它的性能可能不如平时好 例如,我们有
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 0
};
}
changeState(){
console.log('in change state',this.state.data);
this.state.data = 'new value here'
this.setState({});
console.log('in change state after state change',this.state.data);
}
render() {
return (
<div>
<p>{this.state.data}</p>
<a onClick={this.changeState}>Change state</a>
</div>
);
}
}
In this example, we change the state first and then render our component.
在这个例子中,我们首先改变状态,然后渲染我们的组件。
回答by V. Kovpak
Short answer to your question is - NO, react doesn't have sync method setState.
对您问题的简短回答是 - 不,反应没有同步方法setState。
回答by Dustin Kane
I was able to trick React into calling setStatesynchronously by wrapping my code in setTimeout(() => {......this.setState({ ... });....}, 0);. Since setTimeoutputs stuff at the end of the JavaScript event queue, I think React detects the setState is within it and knows it can't rely on a batched setStatecall (which would get added to the end of the queue).
我能够setState通过将我的代码包装在setTimeout(() => {......this.setState({ ... });....}, 0);. 由于setTimeout将东西放在 JavaScript 事件队列的末尾,我认为 React 检测到 setState 在其中,并且知道它不能依赖批处理setState调用(这会被添加到队列的末尾)。

