#reactjs #redux #redux-toolkit
Вопрос:
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=c057c067b76238e7a64d3ba8de37076eamp;language=en-US`;
const movieCastUrl = `https://api.themoviedb.org/3/movie/${movieId}/credits?api_key=c057c067b76238e7a64d3ba8de37076eamp;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;
Привет всем.Когда я нажал на карточку compenent, она привела меня к компоненту SingleMoviePage.Но компонент SingleMoviePage перерисовывается пять раз.Как я могу найти источник этой проблемы ? И как я могу это предотвратить ? Наконец, есть ли какие-либо проблемы с получением MovieCast и MovieDetails в одном и том же крючке useffect ?
репо на github : https://github.com/UmutPalabiyik/hope-movie-app ДЕМОНСТРАЦИЯ : https://hope-movie.web.app/page/1
Комментарии:
1. Я также столкнулся с той же проблемой из-за зависимостей в useEffect.
Ответ №1:
Первые 2 крючка useEffect извлекают данные отдельно, которые затем обновляют ваши локальные состояния, что затем запускает повторную визуализацию.
Если вы не хотите повторно визуализировать после каждой выборки данных (обновления состояния), я бы предложил добавить loading
состояние. Сначала установите значение true и верните значок загрузки в качестве содержимого. Затем, после того как оба movieDetails
и movieCredits
были заполнены, установите значение false и верните фактическое содержимое. Это должно отображаться в общей сложности дважды.
Вы рассматривали graphql? GraphQL может объединить ваши вызовы api в один, а также обрабатывать состояние загрузки и состояние ошибки.
Какое бы решение у вас ни было, повторный рендеринг произойдет, когда вы будете получать данные. Начальный рендеринг не будет содержать никаких данных, и после извлечения данных он должен быть повторно отрисован.
Комментарии:
1. Tnx так много. И можете ли вы проверить мой запрос, который гласит: «css-анимация не работает должным образом после загрузки reactjs» в моем профиле. Все равно я не мог исправить 🙂
Ответ №2:
Вы должны использовать только один хук useEffect, ваш код выполняется для всех трех. С остальным React справится сам.