Home > Net >  TypeError: Cannot read properties of undefined (reading 'map') react
TypeError: Cannot read properties of undefined (reading 'map') react

Time:12-06

I'm trying to get a Tv show to display on multiple cards. I'm just using one Tv show before I start adding any more. So it should basically display one tv show on all the cards.

The error is coming from the tvList.js.

tvList.js

import React from "react";
import Tv from "../tvCard/";
import Grid from "@material-ui/core/Grid";

const TvList = (props) => {
  let tvCards = props.tvshows.map((m) => (
    <Grid key={m.id} item xs={12} sm={6} md={4} lg={3} xl={2}>
      <Tv key={m.id} tv={m} />
    </Grid>
  ));
  return tvCards;
};

export default TvList;

The Tv card seems to be fine and is working in my storybook.

tvCard.js

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import CardMedia from "@material-ui/core/CardMedia";
import CardHeader from "@material-ui/core/CardHeader";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import FavoriteIcon from "@material-ui/icons/Favorite";
import CalendarIcon from "@material-ui/icons/CalendarTodayTwoTone";
import StarRateIcon from "@material-ui/icons/StarRate";
import IconButton from "@material-ui/core/IconButton";
import Grid from "@material-ui/core/Grid";
import img from '../../images/tv-poster-placeholder.png'

const useStyles = makeStyles({
  card: { maxWidth: 345 },
  media: { height: 500 },
  avatar: {
    backgroundColor: "rgb(255, 0, 0)",
  },
});

export default function TvCard(props) {
  const classes = useStyles();
  const tv = props.tv;
  return (
    <Card className={classes.card}>
      <CardHeader className={classes.header} title={tv.name} />
      <CardMedia
        className={classes.media}
        image={
          tv.poster_path
            ? `https://image.tmdb.org/t/p/w500/${tv.poster_path}`
            : img
        }
      />
      <CardContent>
        <Grid container>
          <Grid item xs={6}>
            <Typography variant="h6" component="p">
              <CalendarIcon fontSize="small" />
              {tv.first_air_date}
            </Typography>
          </Grid>
          <Grid item xs={6}>
            <Typography variant="h6" component="p">
              <StarRateIcon fontSize="small" />
              {"  "} {tv.vote_average}{" "}
            </Typography>
          </Grid>
        </Grid>
      </CardContent>
      <CardActions disableSpacing>
        <IconButton aria-label="add to favorites" onClick={null}>
          <FavoriteIcon color="primary" fontSize="large" />
        </IconButton>
        <Button variant="outlined" size="medium" color="primary">
          More Info ...
        </Button>
      </CardActions>
    </Card>
  );
}

tvPage.js

import React from "react";
import Header from "../components/headerTvList";
import FilterCard from "../components/filterTvCard";
import Grid from "@material-ui/core/Grid";
import { makeStyles } from "@material-ui/core/styles";
import TvList from "../components/tvList";

const useStyles = makeStyles({
  root: {
    padding: "20px",
  },
});

const TvListPage = (props) => {
  const classes = useStyles();
  const tvshows = props.tvshows;

  return (
    <Grid container className={classes.root}>
      <Grid item xs={12}>
        <Header title={"Discover Tv Shows"} />
      </Grid>
      <Grid item container spacing={5}>
        <Grid key="find" item xs={12} sm={6} md={4} lg={3} xl={2}>
          <FilterCard />
        </Grid>
        <TvList tvshows={tvshows}></TvList>
      </Grid>
    </Grid>
  );
};
export default TvListPage;

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import TvPage from "./pages/tvPage";

const sample = {

  "backdrop_path": "/wAEWZm2pSopAbqE5dQWE0ET8aR5.jpg",
  "first_air_date": "2021-01-08",
  "genre_ids": [
      10759,
      10765,
      99
  ],
  "id": 114695,
  "name": "Marvel Studios: Legends",
  "origin_country": [
      "US"
  ],
  "original_language": "en",
  "original_name": "Marvel Studios: Legends",
  "overview": "Revisit the epic heroes, villains and moments from across the MCU in preparation for the stories still to come. Each dynamic segment feeds directly into the upcoming series — setting the stage for future events. This series weaves together the many threads that constitute the unparalleled Marvel Cinematic Universe.",
  "popularity": 140.788,
  "poster_path": "/EpDuYIK81YtCUT3gH2JDpyj8Qk.jpg",
  "vote_average": 7.6,
  "vote_count": 515
}
        
    
    
      const tvshows = [sample, sample, sample, sample, sample, sample, sample];

      const App = () => {
        return (
            <TvPage tvshows={tvshows} />
        );
      };
      
      ReactDOM.render(<App />, document.getElementById("root"));

CodePudding user response:

It could be an with the tvPage component.

const tvshows = props.tvshows;

Here the value of tvshows might be empty initially. I'd suggest i your TvList component do an null check.

const TvList = (props) => {
  let tvCards = props.tvshows?.map((m) => (
    <Grid key={m.id} item xs={12} sm={6} md={4} lg={3} xl={2}>
      <Tv key={m.id} tv={m} />
    </Grid>
  ));
  return tvCards;
};

The ? is an [optional chaining] operator(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining).

CodePudding user response:

The error is that for some reason, props.tvshows is undefined within TvList, even though it should be passed down from App to TvPage to TvList. At some point down the line, tvshows is lost.

I would suggest logging all instances of tvshows, starting from when it is first defined in App, then logging in TvPage, then TvList, to see where exactly the problem is coming from. Once you've found it, do some debugging to make the problem stop.

  • Related