首页 > 解决方案 > 基于素数检测的反应集合状态

问题描述

我需要通过单击按钮根据输出的数字更改 React 组件中的状态。该按钮增加一个计数器的状态。如果数字是素数,它应该将 isPrime 状态更改为 true;如果不是 isPrime 应该是假的。

  class Counter extends Component {

    constructor(props) {
        super(props);
        this.state = {
          count:0,
          isPrime: false
        };
      }

checkPrime = (num) => {
    if (num === 1) return false;
    if (num === 2) return true;
    for(var i = 2; i < num; i++) {
        if(num % i === 0) {
            return false; // it isn't prime
        }
    }
    return true; //it is prime
  }

incrementItem = () => {
    this.setState((prevState, { count }) => ({
    count: prevState.count + 1
  }));
    if (this.checkPrime(this.state.count)) {
        this.setState({ isPrime: true });
    }
    else {
        this.setState({ isPrime: false });
    }
}


render() {
    return (
      <div id="mainDiv" className={this.state.isPrime ? 'bgPrime' : ''}>
        <button onClick={this.incrementItem}>Click me</button>
        {<h2>{ this.state.count }</h2> }
      </div>
    );
  }
}

export default Counter;

在 incrementItem 函数中,我无法按照此处的建议使用以下语法:

    this.setState((prevState, { isPrime }) => {
            isPrime: true
     });
// ('Expected an assignment or function call and instead saw an expression  no-unused-expressions')

标签: javascriptreactjs

解决方案


该建议未正确执行。本文建议使用updater function ,这是第一个 setState参数。更新器函数接受先前的状态和当前的道具作为参数并返回新的状态:

this.setState((prevState, props) => ({ isPrime: true }));

由于在新状态中没有使用状态和道具,因此不需要更新器功能。如果更新是无条件的,那就是:

this.setState({ isPrime: true });

但是 updater 函数的目的是防止竞争条件,因为状态更新是异步的。这部分将导致竞争条件,因为state.count它可能在更新之前被访问:

this.setState((prevState, { count }) => ({
  count: prevState.count + 1
}));
if (this.checkPrime(this.state.count)) {
...

相反,两个状态更新都应该使用更新函数来完成,以保持它们的执行顺序:

incrementItem = () => {
  this.setState((prevState) => ({
    count: prevState.count + 1
  }));

  this.setState((prevState) => ({
    isPrime: this.checkPrime(prevState.count)
  }));
}

推荐阅读