How to avoid adding to an array if element already exists
The right condition is
if (!(this.state.likes.filter(e => e.name === person.name).length > 0)) {
// your code
}
The meaning of the condition is:
this.state.likes.filter(e => e.name === person.name).length > 0) This will filter out the array only when an element of the array matches with the provided person object name. It points out that the person is already present in the array
The ! is used to check the opposite condition, because you want enter in your if statement only if person does not exists
EDIT Reading better your code, this could be accomplished with a simpler, cleaner method:
addPerson = (person) => {
let filteredPerson = this.state.likes.filter(like => like.name !== person.name);
this.setState({
likes: [...filteredPerson, person]
})
}
Check out this working snippet: https://stackblitz.com/edit/react-jxebwg
Related videos on Youtube
kayak
I'm learning React and JavaScript. Front-end Developer to be.
Updated on June 04, 2022Comments
-
kayak almost 2 years
I'm making Add to favorite function in React. Thanks to everyone's help I could somehow make that work except for toggling like and dislike. I coded like "likes: this.state.likes.filter(e => e.name !== person.name)" just because someone advised me to code so. To be honest I don't understand the code above maybe because it's ES6 syntax. How does it look like in ES5? And right now that code is not working, elements are not added to the array properly. How do I fix this code?
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> ) } }
-
Joe Taras almost 5 yearsHave you tried with Array.prototype.includes() to check if an element exists in an array. See here: developer.mozilla.org/it/docs/Web/JavaScript/Reference/…
-
buffy almost 5 yearsUsing Set instead of array could be a good idea, too. Avoiding duplicates is the nature of a set afterall. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
-
kayak almost 5 yearsI tried it and it works! "if (this.state.likes.includes(person)) {". Now my problem is I can't figure out how to remove duplicated element in the array. I'm trying like "this.setState({ likes: this.state.likes.splice(person) });" but it won't work :(
-
buffy almost 5 yearstry this.state.likes.splice(this.state.likes.indexOf(person), 1)
-
kayak almost 5 yearsTried the code above but it seems like I messed up everything. If I click for the first time the array is still empty, and if I click another person then previous person is added to the array.
-
Chris Ngo almost 5 years@kayak, I just wrote you solution. Let me know if that's helpful!
-
-
Mosè Raguzzini almost 5 yearsFixed, a parenthesis issue. You cal also check alternatively that length should be < 1, without !
-
kayak almost 5 yearsSo if the array does not include person, then splice? Maybe it's opposite?
-
kayak almost 5 yearsThank you for your detailed explanation. I didn't know .filter removes specific element. However the code is not working as I intended. The toggle happens even when I click other icons.
-
kayak almost 5 yearsIf I click a person and click again it sure toggles, but if I another person before I toggle, the likes array turns empty. Btw thank you for the link. That service looks useful.
-
Chris Ngo almost 5 years@kayak I'm not sure what you mean by other icons? Do you mean the icon that belongs to a different like changes when you click on an icon?
-
kayak almost 5 yearsSorry for the confusion. Maybe I should do "if (likes.map(like => like).includes(person))" ? I removed all the ".name" and it finally worked!
-
kayak almost 5 yearsNot sure if "if (likes.map(like => like).includes(person))" syntax is correct though..
-
Chris Ngo almost 5 years@kayak ahh okay I see what went wrong here. You're already passing person.name into your handleClick function when you render these icons. Also it looks like the likes array is just an array of strings which are just the person names. I thought it would be an object. In this case, we only need .includes(). Let me update my answer to clean up the solution.
-
Chris Ngo almost 5 yearsLet us continue this discussion in chat.