简体   繁体   English

React setState 没有正确更新

[英]React setState not updating properly

this.setState({ selected: 0 }, () => {
    console.log("selected value: " + this.state.selected);
}); 

This prints values other than zero depending on what value selected was before running this code.这将根据运行此代码之前selected值打印零以外的值。 Basically the setState does nothing and I'm not sure why.基本上 setState 什么都不做,我不知道为什么。

Any help would be greatly appreciated.任何帮助将不胜感激。

Edit - Here is some more code编辑 - 这里还有一些代码

import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);

    var selected = 0;

    this.state = {
      selected: selected
    };

    this.handleTap = this.handleTap.bind(this);
  }

  deselect() {
    this.setState({ selected: 0 }, () => {
      console.log("selected: " + this.state.selected);
    }); 
  }

  handleTap() {
    var selected = this.state.selected;

    selected++;

    if(selected >= 2) {
      this.deselect();
    }

    this.setState({selected: selected});
  }

  render() {
    return (
      <div onPointerDown={() => this.handleTap()} style={{width: "100px", height: "100px", backgroundColor: "black"}}></div>
    );
  }
}

export default App;

I now believe I know the issue.我现在相信我知道这个问题。 I think calling setState in handleTap() after calling deselect() is making the selected value stay at a value greater than two.我认为在调用deselect() handleTap()之后在handleTap()调用 setState handleTap()所选值保持大于 2 的值。

Your issue is handleTap .您的问题是handleTap React state updates are asynchronous and "collated", meaning, calling setState several times within a single function means they all get queued up and processed. React 状态更新是异步和“整理”的,这意味着,在单个函数中多次调用setState意味着它们都被排队并处理。

handleTap() {
  var selected = this.state.selected;

  selected++;

  if(selected >= 2) {
    this.deselect();
  }

  this.setState({selected: selected});
}

Here you are setting state twice, but since you aren't doing functional updates using the previous state, the last setState call trumps all previous calls.在这里,您设置了两次状态,但由于您没有使用先前的状态进行功能更新,因此最后一次setState调用胜过所有先前的调用。

You should instead only call one setState per tap handle.相反,您应该只为每个点击句柄调用一个setState

handleTap() {
  var selected = this.state.selected;

  console.log("current selected", selected);

  selected++;

  if (selected >= 2) {
    this.deselect();
  } else {
    this.setState({ selected: selected });
  }
}

编辑深情pascal-w19ng

The problem was here问题出在这里

if(selected >= 2) {
  this.deselect();
}

this.setState({selected: selected});

The deselect() sets the state, and the right afterward, you call another setState to the selected value. deselect()设置状态,然后立即调用另一个setState到所选值。 It can be fixed by simply adding a else statement (so the console.log inside the callback will always be 0 - after you setState to 0)它可以通过简单地添加一个else语句来修复(因此回调中的console.log将始终为 0 - 在您将setState为 0 之后)

 class App extends React.Component { constructor(props) { super(props); var selected = 0; this.state = { selected: selected }; } deselect() { this.setState({ selected: 0 }, () => { console.log("selected: " + this.state.selected); }); } handleTap() { var selected = this.state.selected; selected++; if (selected >= 2) { this.deselect(); } else { this.setState({ selected: selected }); } } render() { return ( <div onPointerDown={() => this.handleTap()} style={{ color: "white", width: "100px", height: "100px", backgroundColor: "black" }} > State: {this.state.selected} </div> ); } } ReactDOM.render( <App />, document.getElementById("react") );
 <div id="react"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The problem was after the if condition, adding an else as shown below would solve the problem.问题出在 if 条件之后,添加如下所示的 else 可以解决问题。

    handleTap() {
      var selected = this.state.selected;
      selected++;
      if(selected >= 2) {
        this.deselect();
      } else {
      this.setState({selected: selected});
      }
    }

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

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