使用UseEffect代替componentDidMount和componentDidUpdate遇到麻烦

时间:2020-08-08 09:28:41

标签: javascript reactjs react-hooks react-router-dom use-effect

我正在尝试使用useEffect,就像在类组件中使用componentDidMount和componentDidUpdate一样。因此,我有一个名为SeasonPage的组件,并且该组件内部是指向具有不同参数的同一组件的链接。但是,当url更改其参数时,该组件不会重新呈现我在useEffect中调用的函数。最初我有一个空的依赖项数组,但是经过一番研究,我添加了props.match.params.seasonid但还是没有运气。我希望有人能展示使用钩子执行此任务的正确方法。 谢谢,

export default function SeasonPage(props) {

    const [season, setSeason] = useState({});
    const [seasonID, setSeasonID] = useState(props.match.params.seasonid);
    const [showID] = useState(props.match.params.id);
    const [episodes, setEpisodes] = useState([]);
    const [show, setShow] = useState({});
    const [otherSeasons, setOtherSeasons] = useState([]);


useEffect(() => {
     getShow();
     getSeasons();
     console.log(props);
     
  },[props.match.params.seasonid]);

  const getShow = () =>{
      axios.get(`https://api.themoviedb.org/3/tv/${showID}?api_key=apikey&language=en-US`)
      .then(results => {
          setShow(results.data)
          setOtherSeasons(results.data.seasons)
      })
      .catch(error =>{
          console.log(error)
      });
  }

const getSeasons = () =>{
    axios.get(`https://api.themoviedb.org/3/tv/${showID}/season/${seasonID}?api_key=apikey&language=en-US`)
    .then(results =>{
        console.log(results);
        setSeason(results.data);
        setEpisodes(results.data.episodes)
    })
    .catch(error =>{
        console.log(error);
        
    });

};

const handleError = (e) =>{
    console.log(e);
    e.target.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/No_image_available.svg/300px-No_image_available.svg.png';

}

let episodesjsx = episodes.map((ep, i) =>{
    return <MovieCard movie={ep} key={i} id={ep.id} title={ep.name} overview={ep.overview} voteAverage={ep.vote_average} backdropPath={ep.still_path} type="episode"/>;
});

let otherSeasonsjsx = otherSeasons.map(seasonx => {
    return seasonx.season_number !== parseInt(seasonID )&&  <SeasonsCard season={seasonx} tvshowID={show.id} />
});

    return (
        <div className="season-page">
            <div className="container">
                <div className="banner" style={{backgroundImage:`url("https://image.tmdb.org/t/p/original/${show.backdrop_path}")`}}>
                    <div className="banner-overlay">
                        <div className="banner-content">
                            <div className="banner-content-poster-div">
                            <img src={`https://image.tmdb.org/t/p/w342/${season.poster_path}`}></img>
                            </div>
                            <div className="banner-content-details">
                                <h1>{show.name}</h1>
                                <h3>{season.name}</h3>
                                <p>{season.air_date}</p>
                                <div className="overview">

                                <p>{season.overview}</p>
                                </div>
                            </div>
                        </div>
                        </div>
                </div>
       
                <div className="scroll-container-div">
                    <h2>{season.name} Episodes</h2>
                    <div className="scroll-div">
                        {episodesjsx}
                    </div>
                </div>
                <div className="scroll-container-div">
                    <h2>Other Seasons</h2>
                    <div className="scroll-div">
                        {otherSeasonsjsx}
                    </div>
                </div>
           
            </div>
        </div>
    )
}

下面是具有按钮的组件,该按钮可链接到要渲染的相同组件。



const useStyles = makeStyles({
  root: {
    maxWidth: 345,
    minWidth: 325,
    margin: '15px',
  },
  media: {   
      height: 250,        
  objectFit: 'cover',      
    
  },
});

export default function SeasonCard(props) {
  const classes = useStyles();
  const description = props.overview ? props.overview.slice(0, 120) + "...": '';
  let pic = `https://image.tmdb.org/t/p/original/${props.season.poster_path}`;
 

  return (
    <Card className={classes.root}>
      <CardActionArea>
        <CardMedia
        className={classes.media}
          component="img"
          alt={props.season.name}
          image={pic}
          title={props.season.name}
        />
        <CardContent>
          <Typography gutterBottom variant="h5" component="h2">
            {props.season.name} ({props.season.episode_count} ep.)
          </Typography>
          <Typography variant="body2" color="textSecondary" component="p">
            {description}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions>
        
        <Button size="small" color="primary" component={Link} to={`/tvshows/${props.tvshowID}/seasons/${props.season.season_number}`} style={{width: '100px'}}>
          Learn More
        </Button>
      </CardActions>
    </Card>
  );
}

这是我的路由器,以备您需要时使用。

    <Route path="/tvshows/:id/seasons/:seasonid" component={SeasonPage} ></Route>

1 个答案:

答案 0 :(得分:0)

我认为这些说法不对。 道具与状态的同步是一种反模式。More on this

const [seasonID, setSeasonID] = useState(props.match.params.seasonid);
const [showID] = useState(props.match.params.id);

相反,直接从道具中获取ID。

useEffect(() => {
    getShow();
    getSeasons();
    console.log(props);

}, [props.match.params]); //excecute code whenever id and/or seasonid changed

const getShow = () => {
    const { id } = props.match.params;

    axios.get(`https://api.themoviedb.org/3/tv/${id}?api_key=apikey&language=en-US`)
        .then(results => {
            setShow(results.data)
            setOtherSeasons(results.data.seasons)
        })
        .catch(error => {
            console.log(error)
        });
}

const getSeasons = () => {
    const { id, seasonid } = props.match.params;

    axios.get(`https://api.themoviedb.org/3/tv/${id}/season/${seasonid}?api_key=apikey&language=en-US`)
        .then(results => {
            console.log(results);
            setSeason(results.data);
            setEpisodes(results.data.episodes)
        })
        .catch(error => {
            console.log(error);

        });

};