在 useEffect 中尝试使用 useState 时出现 TypeError: movieDetails.map 不是函数
2021-07-04
177
import { useSelector, useDispatch } from "react-redux";
import { useEffect, useState } from "react";
import request from "../../requests";
import { fetchMovies } from "../../feautures/movies/moviesSlice";
import "./SingleMoviePage.scss";
import Rating from "../../components/UI/Rating/Rating";
import axios from "axios";
const SingleMoviePage = ({ match }) => {
const dispatch = useDispatch();
const [movieDetails, setMovieDetails] = useState({})
/* params */
const movieId = match.params.id;
const page = match.params.page;
const genre = match.params.genre;
/* movies reducer handle */
const movies = useSelector((state) => state.movies.movies);
const moviesStatus = useSelector((state) => state.movies.status);
/* movieDetails reducer handle */
/* 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`;
useEffect(() => {
const fetchData = async() => {
let response = await axios.get(movieDetailUrl);
response = response.data;
setMovieDetails(response)
}
fetchData()
},[movieDetailUrl])
console.log("data: ",movieDetails )
let content;
if (moviesStatus === "loading") {
<div>Loading ...</div>;
} else if (moviesStatus === "succeeced") {
let movie = movies.find((movie) => movie.id.toString() === movieId);
content = (
<div
className="single-movie__container"
style={{
backgroundImage: `url(${
movie.backdrop_path
? baseImgUrl + movie.backdrop_path
: baseImgUrl + movie.poster_path
})`,
}}
>
<div className="single-movie__information">
<h1 className="single-movie__title">{movie.title}</h1>
<div className="single-movie__rate">
<Rating
rating={movie.vote_average}
className="single-movie__stars"
/>
<div className="single-movie__average">
{movie.vote_average}(Imdb)
</div>
</div>
<p className="single-movie__overview">{movie.overview}</p>
<p className="single-movie__genres">
<label>Genres</label>
{
movieDetails.genres.map(genre => {
console.log("genre: ",genre)
return(
<div>{genre.name}</div>
)
})
}
</p>
</div>
</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;
我正在尝试使用
react-redux
制作一个电影网站。问题是当我尝试使用
useEffect
获取电影详细信息并尝试将其
map
到:
<p className="single-movie__genres">
我收到
TypeError:无法读取未定义的属性“map”
错误,并且我使用
console.log("data: ", movieDetails)
获得空对象 (
data: {})。
但如果我刷新页面,一切都会正常,我得到 data:
{
adult: false,
backdrop_path: "/6MKr3KgOLmzOP6MSuZERO41Lpkt.jpg",
...
}
使用
console.log("data: ", movieDetails)
。为什么我在第一次加载页面时无法获取数据?
3个回答
这是因为您的初始状态不包含对象内的“genres”数组。当 React 尝试处理
movieDetails.genres.map(...)
时,它会失败,因为 movieDetails.genres 未定义(并且未定义当然不支持 map 方法)。要么在您的初始状态中包含空数组,例如:
const [movieDetails, setMovieDetails] = useState({genres:[]})
,要么在您的链中使用“?”运算符,例如:
movieDetails.genres?.map(...)
Tarukami
2021-07-04
.map 方法是数组类型的原型函数。在使用
useState
钩子设置默认值时,您应该将
moviedetails
声明为这样的数组。
const [movieDetails, setMovieDetails] = useState([])
sazzad
2021-07-04
有一点我不明白。据我所知,当组件首次加载时,useEffect 起作用了,然后在 map 函数起作用之后,用数据填充了我的 movieDetails。我的意思是 js 从上到下工作,而 movieStatus 不应该在到达 map 函数之前填充数据吗?
Umut Palabiyik
2021-07-04