使用foreach循环的SetState不起作用

时间:2019-04-24 09:13:38

标签: javascript reactjs

我正在尝试使用以下代码更新状态:

handleCheckBox = () => {
    this.setState(({isCheckd}) => ({isCheckd: !isCheckd, isEnable: !isCheckd}), () => 
      this.props.untracked.forEach((item) => this.setState({ [item.resumeId]: this.state.isCheckd })),
      this.props.tracked.forEach((item) => this.setState({ [item.resumeId]: this.state.isCheckd }))
    );
  }

当我尝试使用forEach函数进行更新时。在第一个循环中,状态会更新,因为您看到条件相同。但在这第一个中得到改变,但在第二个中没有得到改变。如果我更改了它们的写入顺序,则以第一个状态为准,而第二个状态不变。

handleTableCheckboxChange = (e, type) => {
    this.setState({
      [e.target.name]: e.target.checked
    }, () => {
      const checkedItems = this.props[type].filter((item) => this.state[item.resumeId])
      this.setState({
        isCheckd: checkedItems.length === this.props[type].length ? true : false,
        isEnable: checkedItems.length > 1 ? true : false
      });
    });
  }

如何防止这种情况发生?

1 个答案:

答案 0 :(得分:2)

正如我在对上一个问题的评论中所说,您正在打破fundamental rules of React之一:如果要基于现有状态设置状态 ,则您必须< / strong>使用setState的回调版本,而不是将对象传递给的版本。

看那个代码,这样做看起来像这样:

handleCheckBox = () => {
  this.setState(
    ({isCheckd}) => ({isCheckd: !isCheckd, isEnable: !isCheckd}),
    () => this.setState(({isCheckd}) => {
      const newState = {};
      for (const item of [...this.props.untracked, ...this.props.tracked]) {
        newState[item.resumeId] = isCheckd;
      }
      return newState;
    })
  );
}

但是,跳出了一些奇怪的事情:

  1. 目前尚不清楚为什么要在外部setState的完成处理程序中再次调用setState

  2. 不清楚当您对trackeduntracked进行相同操作时为何拥有它们。

如果您可以在一个状态下进行更新,那可能会更好:

handleCheckBox = () => {
  this.setState(({isCheckd}) => {
    const newState = {
      isCheckd: !isCheckd,
      isEnable: !isCheckd
    };
    for (const item of [...this.props.untracked, ...this.props.tracked]) {
      newState[item.resumeId] = isCheckd;
    }
    return newState;
  });
}

关于您更新的问题,handleTableCheckboxChange存在相同的问题(基于将对象传递到setState的现有状态来设置状态),因此适用相同的解决方案(使用回调版本):

handleTableCheckboxChange = ({target: {name, checked}}, type) => {
  this.setState(prevState => {
    const newState = {[name]: checked};
    const checkedItems = this.props[type].filter((item) => prevState[item.resumeId]);
    newState.isCheckd = checkedItems.length === this.props[type].length;
    newState.isEnable = checkedItems.length > 1;
    return newState;
  });
};

(注意,我已经从设置? true : falseisCheckd的行中删除了isEnable===> 已经给您一个布尔值,在那里添加条件运算符毫无用处。)