浏览电影详细信息页面时,React 电影应用程序崩溃
2022-07-23
200
我正在创建一个使用 rapid API 中的电影应用 API 的 React 电影应用。主页上一切都运行正常,我能够以卡片的形式呈现所有电影。我已将应用设置为当用户点击电影卡片时,它应该直接转到 Moviedetail 页面。为此,我使用了 react-router-dom,并且一切都设置正确。单击电影卡片时,它会导航到 Moviedetail 页面,但没有任何内容被呈现,并在浏览器控制台中出现此错误。 (未捕获的 TypeError:无法读取未定义的属性(读取“长度”)在 Details(Details.js:18:1));
但如果我在 MovieDetails 页面中注释 Detail 和 MovieTrailers 组件并取消注释它,则 MovieDetails 页面上的所有内容都会完美呈现。如果我再次刷新页面,它会再次中断,我得到相同的浏览器控制台错误。
import React, {useState, useEffect} from "react";
import {Box} from "@mui/material";
import {useParams} from "react-router-dom";
import MovieTrailers from "../components/MovieTrailers";
import Details from "../components/Details";
import {fetchData, options} from "../utils/fetchData";
function MovieDetails() {
const [movieDetailData, setMovieDetailData] = useState({});
const [movieTrailerData, setMovieTrailerData] = useState([]);
const {id} = useParams();
// console.log(id);
console.log(movieDetailData);
console.log(movieTrailerData);
useEffect(()=>{
const fetchMovieData = async ()=> {
const detailData = await fetchData(`https://movies-app1.p.rapidapi.com/api/movie/${id}`, options);
setMovieDetailData(detailData.result);
const trailerData = await fetchData(`https://movies-app1.p.rapidapi.com/api/trailers/${id}`, options);
setMovieTrailerData(trailerData.result);
}
fetchMovieData();
},[id]);
return(
<Box>
<Details
movieDetailData={movieDetailData}
/>
<MovieTrailers
movieTrailerData={movieTrailerData}
/>
</Box>)
}
export default MovieDetails;
////here is Details component
import React from "react";
import {Box, Stack, Typography, Chip} from "@mui/material";
function Details(props) {
const{image, titleOriginal, countries, genres, rating, release, description} = props.movieDetailData;
return <Stack direction="row" width="100%" sx={{backgroundColor:"#fff"}}>
<img className="movie-poster" src={image} alt="movie-poster"/>
<Stack p="50px" sx={{width:"60%"}}>
<Typography variant="h2" fontWeight="700">
{titleOriginal}
</Typography>
<Box pt="30px" sx={{display:"flex", gap:"30px"}}>
<Chip label={<Typography variant="h6" fontWeight="700">{`rating : ${rating}`}</Typography>} />
<Chip label={<Typography variant="h6" fontWeight="700">{`release: ${release}`}</Typography>} />
</Box>
<Typography variant="h6" pt="30px">
{description.length>600 ? description.substring(0, 601) : description}
</Typography>
<Box pt="30px" sx={{display:"flex", gap:"30px"}}>
<Chip label={<Typography variant="h6" fontWeight="700">{`genre : ${genres[0].name}`}</Typography>} />
<Chip label={<Typography variant="h6" fontWeight="700">{`origin : ${countries[0].name}`}</Typography>} />
</Box>
</Stack>
</Stack>
}
export default Details;
////here is MovieTrailer component
import React from "react";
import {Box, Stack, Typography} from "@mui/material";
import TrailerCard from "./TrailerCard";
import {nanoid} from "nanoid";
function MovieTrailers({movieTrailerData}) {
console.log(movieTrailerData);
return <Box p="30px">
<Typography variant="h4" pt="40px" pb="50px" fontWeight="700" m="auto">{`Watch ${movieTrailerData[0].title}`}
</Typography>
<Stack direction="row" justifyContent="space-between">
{(movieTrailerData.slice(0, 3)).map((trailer)=>(
<TrailerCard trailer={trailer}/>
))}
</Stack>
</Box>
}
export default MovieTrailers;
////here is TrailerCard component
import React from "react";
import {Box, Stack, Typography, Chip} from "@mui/material";
function TrailerCard({trailer}) {
const{thumbnail, ago, author, views, title, url, description} = trailer;
return <Box className="trailer-card" p="10px" backgroundColor="#fff" width="25%">
<Stack>
<a
className="movie-trailer-link"
href={url}
target="_blank"
rel="noreferrer">
<img className="movie-trailer-thumbnail" src={thumbnail} alt="movie-trailer"/>
<Typography pt="10px" variant="body1" fontWeight="700" >
{title}
</Typography>
<Stack paddingBlock="10px" direction="row" justifyContent="space-between" gap="10px" flexWrap="wrap">
<Chip label={`views: ${views}`} />
<Chip label={`ago: ${ago}`}/>
</Stack>
<Typography variant="subtitle2">{`YT: ${author.name}`}</Typography>
<Typography variant="body2" pb="20px">
{description}
</Typography>
</a>
</Stack>
</Box>
}
export default TrailerCard;
2个回答
在影片详情组件中,添加一个最初设置为 true 的加载状态。在 useEffect 中解析 A​​PI 调用后,将加载变量设置为 false。
在 jsx 中,如果加载为 false,则呈现页面数据,否则显示加载器或其他内容
kanuos
2022-07-23
在从后端获取数据之前,movieDetailData 是一个空对象。这就是您收到错误的原因。
首先检查您的 props 是否有合适的键。
import React from "react";
import {Box, Stack, Typography, Chip} from "@mui/material";
function Details(props) {
if (Object.keys(props.movieDetailData).length == 0)
return null;
const{image, titleOriginal, countries, genres, rating, release, description} = props.movieDetailData;
// rest of your code
}
Ahmet Firat Keler
2022-07-23