简体   繁体   English

为什么调用 setState 方法不会立即改变状态?

[英]Why calling setState method doesn't mutate the state immediately?

Ok, i'll try and make this quick because it SHOULD be an easy fix...好的,我会尝试快速完成,因为它应该是一个简单的修复......

I've read a bunch of similar questions, and the answer seems to be quite obvious.我读过一堆类似的问题,答案似乎很明显。 Nothing I would ever have to look up in the first place!我一开始就不需要查找任何东西! But... I am having an error that I cannot fathom how to fix or why its happening.但是......我有一个错误,我无法理解如何修复或为什么会发生。

As follows:如下:

class NightlifeTypes extends Component {
constructor(props) {
    super(props);

    this.state = {
        barClubLounge: false,
        seeTheTown: true,
        eventsEntertainment: true,
        familyFriendlyOnly: false
    }
    this.handleOnChange = this.handleOnChange.bind(this);
}

handleOnChange = (event) => {   
    if(event.target.className == "barClubLounge") {
        this.setState({barClubLounge: event.target.checked});
        console.log(event.target.checked)
        console.log(this.state.barClubLounge)
    }
}

render() {
    return (
        <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/>
    )
}

More code surrounds this but this is where my problem lies.更多的代码围绕着这个,但这是我的问题所在。 Should work, right?应该工作吧?

I've also tried this:我也试过这个:

handleOnChange = (event) => {   
if(event.target.className == "barClubLounge") {
    this.setState({barClubLounge: !this.state.barClubLounge});
    console.log(event.target.checked)
    console.log(this.state.barClubLounge)
}

So I have those two console.log() 's, both should be the same.所以我有这两个console.log() ,两者应该是一样的。 I'm literally setting the state to be the same as the event.target.checked in the line above it!我实际上是在将状态设置为与上面一行中的event.target.checked相同!

But it always returns the opposite of what it should.但它总是返回与它应该相反的结果。

Same goes for when I use !this.state.barClubLounge ;当我使用!this.state.barClubLounge时也是如此; If it starts false, on my first click it remains false, even though whether the checkbox is checked or not is based off of the state!!如果它开始为假,在我第一次点击时它仍然是假的,即使复选框是否被选中是基于状态的!!

It's a crazy paradox and I have no idea whats going on, please help!这是一个疯狂的悖论,我不知道发生了什么,请帮忙!

Reason is setState is asynchronous , you can't expect the updated state value just after the setState , if you want to check the value use a callback method.原因是setState 是异步的,你不能指望在setState之后更新state值,如果你想检查值使用callback方法。 Pass a method as callback that will be get executed after the setState complete its task.将方法作为回调传递,该方法将在setState完成其任务后执行。

Why setState is asynchronous ?为什么 setState 是异步的?

This is because setState alters the state and causes re rendering.这是因为setState改变了state并导致重新渲染。 This can be an expensive operation and making it synchronous might leave the browser unresponsive.这可能是一项昂贵的操作,并且使其synchronous可能会使浏览器无响应。 Thus the setState calls are asynchronous as well as batched for better UI experience and performance.因此setState调用是asynchronous的,并且是批处理的,以获得更好的 UI 体验和性能。

From Doc :来自文档

setState() does not immediately mutate this.state but creates a pending state transition. setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。 Accessing this.state after calling this method can potentially return the existing value.在调用此方法后访问 this.state 可能会返回现有值。 There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.无法保证对 setState 的调用同步操作,并且可能会批处理调用以提高性能。

Using callback method with setState:使用带有 setState 的回调方法:

To check the updated state value just after the setState , use a callback method like this:要在setState之后检查更新的state值,请使用如下回调方法:

setState({ key: value }, () => {
     console.log('updated state value', this.state.key)
})

Check this:检查这个:

 class NightlifeTypes extends React.Component { constructor(props) { super(props); this.state = { barClubLounge: false, seeTheTown: true, eventsEntertainment: true, familyFriendlyOnly: false } } handleOnChange = (event) => { // Arrow function binds `this` let value = event.target.checked; if(event.target.className == "barClubLounge") { this.setState({ barClubLounge: value}, () => { //here console.log(value); console.log(this.state.barClubLounge); //both will print same value }); } } render() { return ( <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> ) } } ReactDOM.render(<NightlifeTypes/>, document.getElementById('app'))
 <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> <div id='app'/>

Since setState is a async function.因为 setState 是一个异步函数。 That means after calling setState state variable does not immediately change.这意味着在调用 setState 后状态变量不会立即改变。 So if you want to perform other actions immediately after changing the state you should use callback method of setstate inside your setState update function.因此,如果您想在更改状态后立即执行其他操作,您应该在 setState 更新函数中使用 setstate 的回调方法。

handleOnChange = (event) => { 
     let inputState = event.target.checked;
      if(event.target.className == "barClubLounge") {
         this.setState({ barClubLounge: inputState}, () => {  //here
             console.log(this.state.barClubLounge);
             //here you can call other functions which use this state 
             variable //
         });        
      }
   }

This is by-design due to performance considerations.出于性能考虑,这是设计使然。 setState in React is a function guaranteed to re-render Component, which is a costly CPU process. React 中的 setState 是一个保证重新渲染 Component 的函数,这是一个代价高昂的 CPU 进程。 As such, its designers wanted to optimize by gathering multiple rendering actions into one, hence setState is asynchronous.因此,它的设计者希望通过将多个渲染动作集中到一个中来进行优化,因此 setState 是异步的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM