【问题标题】:How to avoid adding to an array if element already exists如果元素已经存在,如何避免添加到数组中
【发布时间】:2019-10-21 17:37:21
【问题描述】:

我正在 React 中制作添加到收藏夹功能。感谢大家的帮助,除了切换喜欢和不喜欢之外,我可以以某种方式完成这项工作。我像“喜欢:this.state.likes.filter(e => e.name !== person.name)”这样编码只是因为有人建议我这样编码。老实说,我不明白上面的代码可能是因为它是 ES6 语法。它在 ES5 中是什么样子的?现在代码不起作用,元素没有正确添加到数组中。如何修复此代码?

import React from 'react';
import axios from 'axios';
import IcoMoon from 'react-icomoon';

export default class PersonList extends React.Component {

    state = {
        persons: [],
        likes: []
    }

    componentDidMount() {
        axios.get(`https://jsonplaceholder.typicode.com/users`)
            .then(res => {
                const persons = res.data;
                this.setState({ persons });
            })
    }

    handleClick = person => {

        if (this.state.likes.filter(e => e.name === person.name).length > 0) {

            this.setState({
                likes: this.state.likes.filter(e => e.name !== person.name)
            });

            console.log(this.state.likes);
            return;
        }

        this.setState({
            likes: [...this.state.likes, person]
        });       
    };

    likesTemplate = item => <li key={item}>{item}</li>;

    renderLikes = () => {
        return this.state.likes.map(i => this.likesTemplate(i));
    }

    render() {
        return (
            <div>
                {this.state.persons.map(person => {
                return <li key={person.name}><IcoMoon icon="heart" onClick={() => {this.handleClick(person.name)}} />{person.name}</li>}
            )}

            <h2>Favorite Person</h2>
            <ul>
                {this.renderLikes()}
            </ul>
            </div>
        )
    }
}

【问题讨论】:

  • 您是否尝试过使用 Array​.prototype​.includes() 检查数组中是否存在元素。见这里:developer.mozilla.org/it/docs/Web/JavaScript/Reference/…
  • 使用 Set 而不是数组也是一个好主意。毕竟,避免重复是集合的本质。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 我试过了,效果很好! “如果(this.state.likes.includes(person)){”。现在我的问题是我不知道如何删除数组中的重复元素。我正在尝试像“this.setState({ likes: this.state.likes.splice(person) });”但它不会工作:(
  • 试试 this.state.likes.splice(this.state.likes.indexOf(person), 1)
  • 尝试了上面的代码,但似乎我把一切都搞砸了。如果我第一次点击数组仍然是空的,如果我点击另一个人,那么前一个人就会被添加到数组中。

标签: arrays reactjs setstate


【解决方案1】:

正确的条件是

if (!(this.state.likes.filter(e => e.name === person.name).length > 0)) {
  // your code
}

条件的含义是:

this.state.likes.filter(e => e.name === person.name).length > 0) 只有当数组的元素与提供的 person 对象 name 匹配时,这才会过滤掉数组。它指出 person 已经存在于数组中

! 用于检查相反的条件,因为您只想在人员不存在时输入 if 语句

编辑 更好地阅读您的代码,这可以通过更简单、更简洁的方法来完成:

  addPerson = (person) => {
    let filteredPerson = this.state.likes.filter(like => like.name !== person.name);
    this.setState({
      likes: [...filteredPerson, person]
    })        
  }

查看这个有效的 sn-p: https://stackblitz.com/edit/react-jxebwg

【讨论】:

  • 已修复,括号问题。您还可以检查长度应为 !
  • 那么如果数组不包含人,那么拼接呢?也许是相反的?
  • 如果我单击一个人并再次单击它肯定会切换,但如果我在切换之前另一个人,likes 数组将变为空。顺便说一句,谢谢你的链接。该服务看起来很有用。
【解决方案2】:

您可以通过几种不同的方式来解决此问题。

编辑:现在我们知道 like 只是一个字符串数组

使用.includes()

handleClick = person => {
    const likes = this.state.likes
    //check to see if person has already liked 
    if (likes.includes(person)) {
       //user has already liked. Choose one option (1 or 2)
       
       //Option 1: create a new like array without the current user
       const newLikes = likes.filter((like) => like !== person)
   
       //Option 1: update state with new likes
       this.setState({
          likes: newLikes
       })

       //Option 2: or do nothing
       return;

    //this executes if the user has not liked yet
    } else {
      this.setState({
        likes: [...likes, person]
      })
    }    
};

所以我所说的“执行以下操作之一”取决于您希望您的功能如何表现。

选项 1: 如果您想创建一种切换效果,用户已经喜欢该项目。您应该选择选项一,我们在其中创建新的 arr 并更新状态。这将“不喜欢”,从喜欢的数组中删除用户。然后点击

选项 2: 就是什么都不做。如果用户点击按钮并且他们已经喜欢它,这只会保持状态不变。

【讨论】:

  • 感谢您的详细解释。我不知道 .filter 删除特定元素。但是代码没有按我的预期工作。即使我单击其他图标,也会发生切换。
  • @kayak 我不确定你说的其他图标是什么意思?你的意思是当你点击一个图标时,属于不同like的图标会发生变化?
  • 很抱歉给您带来了困惑。也许我应该做“if (likes.map(like => like).includes(person))”?我删除了所有的“.name”,它终于奏效了!
  • 不确定“if (likes.map(like => like).includes(person))” 语法是否正确..
  • @kayak 好吧,我知道这里出了什么问题。当您呈现这些图标时,您已经将 person.name 传递到您的 handleClick 函数中。此外,likes 数组看起来只是一个字符串数组,它们只是人名。我以为这将是一个对象。在这种情况下,我们只需要 .includes()。让我更新我的答案以清理解决方案。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多