Search code examples
javascriptreactjstypesequalitycoercion

Javascript String Equality with "==="


Im writing a react application and while trying to get all warnings out I found a weird bug...

handleLike = id => {
const movies = [...this.state.movies];
const movie = movies.filter(obj => obj._id === id);
if (movie.map(obj => obj.liked) == "fa fa-heart-o") {
  movie.map(obj => (obj.liked = "fa fa-heart"));
  this.setState({ movies });
} else {
  movie.map(obj => (obj.liked = "fa fa-heart-o"));
  this.setState({ movies });
}

In if (movie.map(obj => obj.liked) == "fa fa-heart-o") I dont type check with (===) because it will be falsy for some reason, but obj.liked after Console Logging it with typeof, it says it is a String, so it definetly should be truthy, even after I added ToString() it did not get truthy... I double checked everything, am I missing something ?

Thanks in Advance!


Solution

  • You're doing a lot of unnessary mapping.

    1) movies.filter(obj => obj._id === id); will return an array of one element which is a movie object. To grab the actual movie object you need to use movies.filter(obj => obj._id === id)[0]; instead. You might also want to consider using find (to grab the movie object) or findIndex to identify the index of the movie you want.

    2) if (movie.map(obj => obj.liked) == "fa fa-heart-o") makes no sense - you're trying to compare an array (map will always return a new array) to a string. I'm surprised that works at all.

    Based on your comment I might rewrite your code as follows:

    handleLike = id => {
    
      const movies = [...this.state.movies];
    
      // Find the index of the movie where `_id` matches `id`
      const movie = movies.find(obj => obj._id === id);
    
      // If the movie at the index is liked (either true/false),
      // give the object a new property "icon" and give it a heart
      if (movie.liked) {
        movie.icon = "fa fa-heart";
      } else {
    
        // Otherwise give it an empty heart
        movie.icon = "fa fa-heart-o";
      }
    
      // Set the new state (only once)
      this.setState({ movies });
    
    }