Ahmad Nadeem
Ahmad Nadeem

Reputation: 100

How to use setState in functional component React?

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;
}

Upvotes: 2

Views: 245

Answers (1)

Ryan Le
Ryan Le

Reputation: 8412

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

Upvotes: 2

Related Questions