SetState和PreviousState

时间:2018-09-24 22:43:13

标签: javascript reactjs

我是React的新手,可能遇到线程问题。

我有一个父类,它创建一系列按钮(通过数组映射)。

父类将按钮添加到计时器上的数组。子类具有onclick属性,该属性调用父方法来删除按钮。

似乎“删除”按钮并不总是会删除右键。我正在将setState与previousState功能一起使用。我想知道我做错了什么。

我将展示父类和子类。我尝试不包括所有导入类和其他类来简化问题,对不起代码仍然很长。

父母:

class PanelDiv extends Component {
  constructor(props) {
    super(props);
    this.state = { items: [0] };
    this.addChild = this.addChild.bind(this);
    this.buttonClickHandler = this.buttonClickHandler.bind(this);
  }

  render() {
    return (
      <div
        id="DivBackground"
        onLoad={() => this.PanelLoaded()}
        style={{
          width: "100%",
          height: "100%",
          backgroundImage: "url(" + BackgroundImage + ")",
          backgroundSize: "cover"
        }}
      >
        {this.state.items.map(item => (
          <NumberButton
            key={"Nb" + item.toString()}
            parentClickHandler={this.buttonClickHandler}
            id={"Nb" + item.toString()}
          />
        ))}
      </div>
    );
  }

  componentDidMount() {
    setInterval(this.addChild, Settings.COMPONENT_ADD_INTERVAL);
  }

  buttonClickHandler(clientId) {
    this.setState((previousState, currentProps) => {
      var foundIndex = previousState.items.findIndex(function(element) {
        console.log(clientId);
        return element.toString() === clientId.substring(2);
      });

      previousState.items.splice(foundIndex, 1);
      return { items: previousState.items };
    });
  }

  addChild() {
    this.setState((previousState, currentProps) => {
      return {
        items: previousState.items.concat([
          previousState.items[previousState.items.length - 1] + 1
        ])
      };
    });
  }
}

孩子:

class NumberButton extends Component {
  constructor(props) {
    super(props);
    var varLeft = (0 + Math.random() * (100 - 0)).toString() + "%";
    var timeoutValue =
      Settings.BUTTON_SPEED_MIN +
      Math.random() * (Settings.BUTTON_SPEED_MAX - Settings.BUTTON_SPEED_MIN);
    var numberValue = Math.round(Math.random() * Settings.MAX_NUMBER);
    this.buttonClicked = this.buttonClicked.bind(this);

    this.state = {
      clientId: props.id,
      wavePath: Waves[numberValue],
      left: varLeft,
      top: 0,
      counter: "Hello",
      timeoutValue: timeoutValue,
      numberValue: numberValue
    };
  }

  updateCount() {
    this.setState((prevState, props) => {
      return { top: prevState.top + 1 };
    });
    setTimeout(() => this.updateCount(), this.state.timeoutValue);
  }

  componentDidMount() {
    this.updateCount();
  }

  render() {
    return (
      <button
        id={this.state.clientId}
        onClick={() => this.buttonClicked()}
        style={{
          color: "white",
          fontSize: Settings.BUTTON_FONT_SIZE,
          fontFamily: "Verdana",
          border: "none",
          backgroundColor: "Transparent",
          backgroundSize: "cover",
          backgroundImage: "url(" + CoconutImage + ")",
          position: "absolute",
          left: this.state.left,
          top: this.state.top,
          width: Settings.BUTTON_WIDTH_AND_HEIGHT,
          height: Settings.BUTTON_WIDTH_AND_HEIGHT
        }}
      >
        {this.state.numberValue}
      </button>
    );
  }

  buttonClicked() {
    var audio = new Audio(this.state.wavePath);
    audio.play();
    this.props.parentClickHandler(this.state.clientId);
  }
}

2 个答案:

答案 0 :(得分:2)

您不应突变状态下的对象。您应该根据以前的状态返回新对象

 
  buttonClickHandler(clientId) {
    this.setState((previousState, currentProps) => ({
      items: previousState.items.filter(element => (
        element.toString() !== clientId.substring(2))
      )
    }));
  }

尝试一下,可能会有所帮助。

答案 1 :(得分:0)

该问题是由于重复的密钥问题(其值为NaN)引起的。

这是解决方法:

  addChild() 
  {

    this.setState((previousState, currentProps) => {

        if (previousState.items.length == 0)
          return {items:[0]};
        else
          return {items: previousState.items.concat([previousState.items[previousState.items.length-1]+1])};
    });
  }