Home > Software engineering >  react movie app breaking when navigating movie detail page
react movie app breaking when navigating movie detail page

Time:07-24

i am creating a react movie app that uses an movie app API from rapid API. on home page everything is working perfectly and I am able to render all movies in the form of cards. i have set the app in such a way that when user clicks on movie card it should direct to Moviedetail page. for this i am using react-router-dom and everything is set up right. on clicking movie card it does navigate to Moviedetail page but nothing is being rendered and getting this error in browser console. (Uncaught TypeError: Cannot read properties of undefined (reading 'length') at Details (Details.js:18:1));

but if i comment Detail and MovieTrailers component in MovieDetails page and uncomment it then everything on MovieDetails page is rendered perfectly. again if i refresh the page it breaks again and i get the same browser console error.

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;

CodePudding user response:

movieDetailData is an empty object before you fetch your data from backend. That's why you get an error.

First check if your props has suitable keys.

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
}

CodePudding user response:

In your movie detail component, add a loading state initially set to true. Upon resolution of the API call in the useEffect, set the loading variable to false.

In the jsx, render the page data if loading is false else show a loader or something else

  • Related