在React中向状态数组添加值

时间:2018-04-11 19:47:49

标签: javascript reactjs

我试图完成两件事。一,onClick,我正在向州财产cardPairs添加值。我制作了一个状态对象的副本,并使用concat来添加一个值。我需要点击三次才能创建匹配项。我第一次点击,我得到空数组,然后在两次后续的正确点击,我将匹配。使用push不会对我的副本起作用,我得到一个"无法消费"错误,当尝试推送时,我得到"对象不可扩展"。如何通过两次点击匹配? 第二个问题是从UI中删除匹配的项目。

class CardCollectionTwo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hidden: false,
      cardPairs: []
    };
    this.compareCards = this.compareCards.bind(this);
  }

  compareCards(e) {
    const pairs = Object.freeze(this.state.cardPairs)
    console.log(pairs)
    this.setState({ cardPairs: pairs.concat(e.target.value) });
    console.log(this.state);
    if(pairs[0] === pairs[1] && pairs.length!== 0){
      console.log('MATCH')
    }else if(pairs.length === 2){
        this.setState(prevState => ({ cardPairs: [] }))
   }
 }
 render() {
    let cards = this.props.cardsEasy["cards"].map((item, index) => {
      return (
    <button
      style={btn}
      value={item}
      id={item}
      onClick={this.compareCards}
      key={item + index}
    >
      {item}
    </button>
  );
});
return <CardTwo cards={cards} />;
 }
   }

export default CardCollectionTwo;

1 个答案:

答案 0 :(得分:2)

Push和Object.freeze()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

Object.freeze()可以防止元素添加到数组中(在您的情况下,通过推送)。 Object.freeze()阻止对其应用的任何内容(数组推送/修改,对象等)的添加,删除和更改。要正确复制,您可以使用Array.slice()this.state.cardPairs.slice()),它会返回源的浅表副本。

concat不会修改数组,而push会修改数组。 concat()返回一个新数组,它是2个数组的组合,而push()则为当前数组添加一个元素。这就是push()对冻结对象无效的原因,而concat则有效。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

回答匹配的问题:

if (pairs[0] === pairs[1] && pairs.length!== 0){
  console.log('MATCH')
} else if(pairs.length === 2){
    this.setState(prevState => ({ cardPairs: [] }))
}

您的逻辑中存在错误。基本上,您连接新的对值并将其提交到您的状态(通过this.setState({ cardPairs: pairs.concat(e.target.value }))。但是,此if条件依赖于e.target.value,因此pairs变量已过时。

此外,在代码方面,您严格来说只是比较数组的前两个元素,这会导致无限的不匹配问题。

解决方案

我们可以采用不同的方法:首先,每当点击一个新的唯一值时,将其添加到数组中。但是,如果我们得到一个已经在数组中的值,那么这意味着我们有一个匹配。然后我们可以过滤掉该元素(可能还有一个删除函数也可以正常工作)。这意味着我们的对将始终只包含唯一值,并且只要匹配就会丢弃唯一值。

const pairs = this.state.cardPairs.slice();
if (pairs.includes(e.target.value)) {
  console.log("Match");
  this.setState({ cardPairs: pairs.filter(el => el != e.target.value )})
} else {
  // Otherwise, add more elements to the list.
  this.setState({ cardPairs: pairs.concat(e.target.value) });
}

用户点击1: [1]

用户再次点击1: []

用户点击0,1: [0,1]

用户点击1: [0]

沙箱:https://codesandbox.io/s/4jmjp3l94x