反应setState更新不正确

时间:2020-02-26 04:14:40

标签: javascript reactjs

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

这将根据运行此代码之前的值selected输出除零以外的值。基本上,setState什么都不做,我不确定为什么。

任何帮助将不胜感激。

编辑-这是更多代码

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;

我现在相信我知道这个问题。我认为在调用handleTap()之后在deselect()中调用setState会使所选值保持大于两个的值。

3 个答案:

答案 0 :(得分:1)

您的问题是handleTap。 React状态更新是异步的和“整理的”,这意味着在单个函数中多次调用setState意味着它们都被排队并处理。

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

  selected++;

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

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

这里您要设置两次状态,但是由于您没有使用先前的状态进行功能更新,因此最后一个setState调用胜过所有先前的调用。

您应该只为每个点击手柄调用一个setState

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

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

  selected++;

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

Edit affectionate-pascal-w19ng

答案 1 :(得分:0)

问题出在这里

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

this.setState({selected: selected});

deselect()设置状态,然后在右边,您将另一个setState调用为所选值。只需添加一条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>

答案 2 :(得分:-2)

问题出在if条件之后,如下所示添加else即可解决问题。

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