2

I was using classes. I changed it to functional components. But in handleLike method. I cant seem to understand how to use setState. Anyhelp with how to do it? In my current useState im getting array of objects. When I click on like button it displays an error that movies.map is not a function. Thankyou

movies.jsx

import React, { Component, useState } from "react";
import { getMovies } from "../services/fakeMovieService";
import Like from "./like";
function Movies() {
  const initialMovies = getMovies();
  const [movies, setMovies] = useState(initialMovies);

  const handleDelete = (movie) => {
    setMovies((movies) => movies.filter((m) => m._id !== movie._id));
  };

    const handleLike = (movie) => {
        const movies = [...movies]
        const index = movies.indexOf(movie)
        movies[index] = { ...movie[index]}
        movies[index].liked = !movies[index].liked
        setMovies({ movies })
  };
  const { length: count } = movies;
  if (count === 0) return <p>There are no movies in database</p>;
  return (
    <React.Fragment>
      <p> Showing {count} movies in the database</p>
      <table className="table">
        <thead>
          <tr>
            <th>Title</th>
            <th>Genre</th>
            <th>Stock</th>
            <th>Rate</th>
            <th></th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {movies.map((movie) => (
            <tr key={movie._id}>
              <td>{movie.title}</td>
              <td>{movie.genre.name}</td>
              <td>{movie.numberInStock}</td>
              <td>{movie.dailyRentalRate}</td>
              <td>
                <Like liked={movie.liked} onClick={()=> handleLike(movie)} />
              </td>
              <td>
                <button
                  onClick={() => handleDelete(movie)}
                  className="btn btn-danger btn-sm"
                >
                  Delete
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </React.Fragment>
  );
}

Like.jsx

   class Like extends React.Component {
    render() {
        let classes = "fa fa-heart";
        if (!this.props.liked) classes+= "-o"
        return (
          <i
            className={classes}
            aria-hidden="true"
                onClick={this.props.onClick}
                style={{cursor:"pointer"}}
          ></i>
        );
    }
}

JSON FILE

const movies = [
  {
    _id: "5b21ca3eeb7f6fbccd471815",
    title: "Terminator",
    genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
    numberInStock: 6,
    dailyRentalRate: 2.5,
        publishDate: "2018-01-03T19:04:28.809Z",
    liked: true,
  },
  {
    _id: "5b21ca3eeb7f6fbccd471816",
    title: "Die Hard",
    genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
    numberInStock: 5,
    dailyRentalRate: 2.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd471817",
    title: "Get Out",
    genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
    numberInStock: 8,
    dailyRentalRate: 3.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd471819",
    title: "Trip to Italy",
    genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
    numberInStock: 7,
    dailyRentalRate: 3.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd47181a",
    title: "Airplane",
    genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
    numberInStock: 7,
    dailyRentalRate: 3.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd47181b",
    title: "Wedding Crashers",
    genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
    numberInStock: 7,
    dailyRentalRate: 3.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd47181e",
    title: "Gone Girl",
    genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
    numberInStock: 7,
    dailyRentalRate: 4.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd47181f",
    title: "The Sixth Sense",
    genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
    numberInStock: 4,
    dailyRentalRate: 3.5
  },
  {
    _id: "5b21ca3eeb7f6fbccd471821",
    title: "The Avengers",
    genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
    numberInStock: 7,
    dailyRentalRate: 3.5
  }
];

export function getMovies() {
  return movies;
}
4
  • what are you expecting? An array of objects sounds reasonable? Commented Sep 12, 2021 at 8:28
  • it displays an error that movies.map is not a function. Commented Sep 12, 2021 at 8:29
  • can you provide a live demo? and why setMovies({ movies} ) is movies supposed to be an array or object of arrays? cuz map function is for arrays and I suppose you want it to be an array of object Commented Sep 12, 2021 at 8:33
  • It would help if we coudl see the code that triggers delete also Commented Sep 12, 2021 at 8:34

1 Answer 1

2

You have a few redundant object/array assignment in your code

So, update your handleLike like so:

const handleLike = (movie) => {
    const _movies = [...movies];
    const index = movies.indexOf(movie);
    _movies[index].liked = !movies[index].liked;
    setMovies(_movies);
  };

Working Example:

Edit lively-worker-vhmi6

Sign up to request clarification or add additional context in comments.

2 Comments

This worked for me. But it was weird as in case of classes that code was working perfectly fine.
True, class component state receives an object, you are correct if this is a class, but in functional component, setState receive a straight variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.