React 18 中通过路由参数动态控制组件行为的完整实践

在 react 18 + react router v6 应用中,可通过路由配置传递 props(如 `listmovies`)并结合 `uselocation` 监听路由变化,实现组件逻辑的动态化与复用,避免硬编码和重复渲染问题。

要在 React 18 中让 Movielist 组件根据当前路由动态获取不同电影列表(如 / 对应 now_playing,/top-rated 对应 top_rated),核心在于将路由意图显式地作为 prop 传入组件,并在组件内部响应式使用该值——而非依赖 URL 解析或状态推断。

首先,确保已在 Movielist.jsx 中正确接收并使用 listMovies prop:

import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom'; // ✅ 必须引入
import axios from 'axios';
import './Movielist.css';
import Moviecard from '../Moviecard/Moviecard';

function Movielist({ listMovies }) { // ✅ 解构接收路由传入的 prop
  const API_URL = 'https://api.themoviedb.org/3';
  const [movies, setMovies] = useState([]);
  const location = useLocation(); // ✅ 用于监听路由变更

  const getMovies = async () => {
    try {
      const response = await axios.get(`${API_URL}/movie/${listMovies}`, {
        params: {
          api_key: process.env.REACT_APP_API_KEY,
        },
      });
      setMovies(response.data.results);
    } catch (error) {
      console.error('Failed to fetch movies:', error);
      setMovies([]);
    }
  };

  const displayMovies = () => {
    return movies.map((movie) => (
      
    ));
  };

  // ✅ 依赖项必须包含 listMovies,否则切换路由时不会重新请求
  useEffect(() => {
    getMovies();
  }, [listMovies]); // ⚠️ 注意:这里应依赖 listMovies,而非 location!

  // 动态标题优化(可选但推荐)
  const getPageTitle = () => {
    switch (listMovies) {
      case 'now_playing': return 'Now Playing';
      case 'top_rated': return 'Top Rated';
      default: return 'Movies';
    }
  };

  return (
    <>
      

{getPageTitle()}

{displayMovies()} ); } export default Movielist;

? 关键修正与最佳实践说明:

  • useEffect 的依赖项必须是 [listMovies],而非 [location]。因为 listMovies 是由父路由明确传入的、决定数据源的唯一变量;location 对象本身在路由跳转时虽会变,但其变化并不直接反映业务逻辑差异,且可能因对象引用变化导致不必要的重复请求。
  • useLocation() 在本例中非必需——除非你需要访问 location.search 或 location.state 等额外信息。当前场景下,listMovies 已完全承载路由语义,更简洁、更可控。
  • 路由配置(App.js)保持原样即可,} 已是标准且推荐的做法,符合“声明式路由 + 显式数据流”原则。
  • 建议添加 try/catch 错误处理,提升健壮性;并用 switch 动态生成页面标题,增强可维护性。

✅ 最终效果:组件完全解耦、高度复用,同一 Movielist 可无缝支持任意 TMDB 列表端点(如未来扩展 /upcoming 或 /popular),只需在路由中传入对应字符串即可。