在使用 UseEffect 代替 componentDidMount 和 componentDidUpdate 时遇到问题

Having trouble with using UseEffect in place of componentDidMount and componentDidUpdate

我正在尝试应用 useEffect,就像您在 class component.So 中使用 componentDidMount 和 componentDidUpdate 一样,我有一个名为 SeasonPage 的组件,并且在该组件内部是 links具有不同参数的相同组件。但是,当 url 更改其参数时,组件不会重新呈现我在 useEffect 中调用的函数。起初我有一个空的依赖数组,但经过一些研究我添加了 props.match.params.seasonid 但仍然没有 luck.I 希望有人可以展示使用钩子来完成这项任务的正确方法。 谢谢,

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>
    )
}

下面是具有按钮的组件 link 到正在呈现的同一组件。



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>

我觉得这些台词不对。 道具与状态的同步是anti-pattern. (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);

        });

};