Reputation: 323
import { useSelector, useDispatch } from "react-redux";
import { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { IoMdArrowRoundBack } from "react-icons/io";
import axios from "axios";
import { fetchMovies } from "../../feautures/movies/moviesSlice";
import Rating from "../../components/UI/Rating/Rating";
import request from "../../requests";
import "./SingleMoviePage.scss";
import SimilarMovies from "../../components/SimilarMovies/SimilarMovies";
const SingleMoviePage = ({ match }) => {
const dispatch = useDispatch();
const [movieDetails, setMovieDetails] = useState({});
const [movieCredits, setMovieCredits] = useState({});
const history = useHistory();
console.log("single rendered")
// number month to string
const date = new Date(movieDetails.release_date);
const dateWithMonthName =
date.getFullYear() +
"-" +
date.toLocaleString("en-EN", { month: "long" }) +
"-" +
date.getDay();
/* params */
const movieId = match.params.id;
const page = match.params.page;
const genre = match.params.genre;
/* movies reducer handle */
const moviesStatus = useSelector((state) => state.movies.status);
/* base urls */
const baseImgUrl = "https://image.tmdb.org/t/p/original";
const movieDetailUrl = `https://api.themoviedb.org/3/movie/${movieId}?api_key=c057c067b76238e7a64d3ba8de37076e&language=en-US`;
const movieCastUrl = `https://api.themoviedb.org/3/movie/${movieId}/credits?api_key=c057c067b76238e7a64d3ba8de37076e&language=en-US`;
// go home page
const goHOme = () => {
history.goBack()
};
// fetch movie cast
useEffect(() => {
const fetchMovieCast = async () => {
let response = await axios.get(movieCastUrl);
response = response.data;
setMovieCredits(response);
};
fetchMovieCast();
}, [movieCastUrl]);
// fetch movie details
useEffect(() => {
const fetchMovieDetails = async () => {
let response = await axios.get(movieDetailUrl);
response = response.data;
setMovieDetails(response);
};
fetchMovieDetails();
}, [movieDetailUrl]);
let content;
if (moviesStatus === "loading") {
} else if (moviesStatus === "succeeded") {
content = (
<div
className="single-movie__container"
style={{
backgroundImage: `url(${
movieDetails.backdrop_path
? baseImgUrl + movieDetails.backdrop_path
: baseImgUrl + movieDetails.poster_path
})`,
}}
>
<div className="single-movie__details">
<IoMdArrowRoundBack
className="single-movie__back"
onClick={goHOme}
size={65}
color={"#e50914"}
/>
<h1 className="single-movie__title">{movieDetails.title}</h1>
<div className="single-movie__rate">
<Rating
rating={movieDetails.vote_average}
className="single-movie__stars"
/>
</div>
<p className="single-movie__overview">{movieDetails.overview}</p>
<div className="single-movie__informations single-movie__informations--genres">
<label className="single-movie__informations-heading">Genres</label>
<div className="single-movie__informations-container">
{movieDetails.genres?.map((genre) => {
return <div className="single-movie__info">{genre.name}</div>;
})}
</div>
</div>
<div className="single-movie__informations single-movie__informations--stars">
<label className="single-movie__informations-heading">
Starring
</label>
<div className="single-movie__informations-container">
{movieCredits.cast?.slice(0, 4).map((star) => {
return <div className="single-movie__info">{star.name}</div>;
})}
</div>
</div>
<div className="single-movie__informations single-movie__informations--released">
<label className="single-movie__informations-heading">
Release Date
</label>
<div className="single-movie__informations-container">
<div className="single-movie__info">{dateWithMonthName}</div>
</div>
</div>
<div className="single-movie__informations single-movie__informations--production">
<label className="single-movie__informations-heading">
Production
</label>
<div className="single-movie__informations-container">
{movieDetails.production_countries?.slice(0, 2).map((country) => {
return <div className="single-movie__info">{country.name}</div>;
})}
</div>
</div>
</div>
<SimilarMovies movieId={movieId} />
</div>
);
}
useEffect(() => {
if (genre === "POPULAR") {
dispatch(fetchMovies(request.fetchPopular(page)));
} else if (genre === "NOW PLAYING") {
dispatch(fetchMovies(request.fetchNowPlaying(page)));
} else if (genre === "UP COMING") {
dispatch(fetchMovies(request.fetchUpComing(page)));
}
}, [dispatch, genre, page]);
return <div className="single-movie">{content}</div>;
};
export default SingleMoviePage;
Hi all.When i clicked Card compenent it navigate me to the SingleMoviePage component.But SingleMoviePage component re-render five times.How can i find this issues's source ? And how can i prevent that ? Finally is there any problem to fetch MovieCast and MovieDetails in same useEffect hook ?
github repo : https://github.com/UmutPalabiyik/hope-movie-app demo : https://hope-movie.web.app/page/1
Upvotes: 0
Views: 3466
Reputation: 41
The first 2 useEffect hooks fetch data separately which then update your local states, which then triggers re-rendering.
If you don't want to re-render after each data fetch (state update), I'd suggest adding a loading
state. Set it to true first and return a loading icon as your content. Then after both movieDetails
and movieCredits
have been populated, set it to false and return the actual content. This should render twice in total.
Have you considered graphql? GraphQL can combine your api calls into one and it also handles loading state and error state.
Whatever solution you have, re-rendering will happen when you are fetching data. Initial render won't have any data and after fetching data it must re-render.
Upvotes: 1
Reputation: 252
You should use only one useEffect hook your code is running for all three. React will handle the rest itself.
Upvotes: 0