You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现宝可梦详情页动态路由:单文件适配多URL

宝可梦网站动态路由实现方案

1. App.jsx:配置动态路由

移除重复的BrowserRouter(createBrowserRouter搭配RouterProvider是React Router v6的正确用法),将固定的/pikachu路由替换为动态路由:pokemonName,让所有宝可梦名称的路径都能匹配到Pokemon组件:

import React from "react";
import Pokemons from "./Pokemons";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Pokemon from "./Pokemon";

function App() {
  const router = createBrowserRouter([
    {
      path: "/",
      element: <Pokemons />,
    },
    {
      path: "/:pokemonName", // 动态路由参数,匹配任意宝可梦名称
      element: <Pokemon />,
    },
  ]);
  return (
    <div>
      <RouterProvider router={router} />
    </div>
  );
}

export default App;

2. Pokemons.jsx:生成动态跳转链接

把固定的Link目标改成对应宝可梦的名称,同时删除无用的routerPath状态:

import React, { useEffect, useState } from "react";
import "./App.css";
import { Link } from "react-router-dom";

function Pokemons() {
  const [pokemonDetails, setPokemonDetails] = useState([]);
  
  useEffect(() => {
    async function fetchData() {
      const response = await fetch(
        "https://pokeapi.co/api/v2/pokemon?limit=20"
      );
      const data = await response.json();
      setPokemonDetails(
        await Promise.all(data.results.map((p) => fetchPokemonDetails(p.url)))
      );
    }
    fetchData();
  }, []);

  async function fetchPokemonDetails(url) {
    const response = await fetch(url);
    const data = await response.json();
    return data;
  }

  return (
    <div>
      <h2>Pokemony</h2>
      <div id="pokemony">
        {pokemonDetails.map((element, index) => (
          <div className="jedenBlok" key={index}>
            <h2 id={"Napis " + element.name} className="pokemoN">
              {element.name}
            </h2>
            <img
              src={element.sprites.front_default}
              alt={`Pokemon ${index + 1}`}
              id={"Pokemon " + element.name}
              className="pokemon"
            />
            {/* 动态生成对应宝可梦的跳转链接 */}
            <Link to={`/${element.name}`}>查看详情</Link>
          </div>
        ))}
      </div>
    </div>
  );
}

export default Pokemons;

3. Pokemon.jsx:根据路由参数获取对应宝可梦详情

使用useParams获取路由中的宝可梦名称,只请求该宝可梦的接口数据,同时添加加载和错误状态提示:

import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";

function Pokemon() {
  const [pokemon, setPokemon] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const { pokemonName } = useParams(); // 获取路由中的宝可梦名称参数

  useEffect(() => {
    async function fetchPokemon() {
      try {
        setLoading(true);
        // 根据路由参数请求对应宝可梦的详情
        const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`);
        if (!response.ok) throw new Error("宝可梦数据获取失败");
        const data = await response.json();
        setPokemon(data);
        setError(null);
      } catch (err) {
        setError(err.message);
        setPokemon(null);
      } finally {
        setLoading(false);
      }
    }
    fetchPokemon();
  }, [pokemonName]); // 路由参数变化时重新请求数据

  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error}</div>;
  if (!pokemon) return <div>未找到该宝可梦</div>;

  return (
    <div>
      <Link to="/">返回首页</Link>
      <div>
        <h1>{pokemon.name}</h1>
        <img src={pokemon.sprites.front_default} alt={pokemon.name} />
        <p>身高:{pokemon.height / 10}m</p>
        <p>体重:{pokemon.weight / 10}kg</p>
        <h3>属性:</h3>
        <ul>
          {pokemon.types.map((type, idx) => (
            <li key={idx}>{type.type.name}</li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default Pokemon;

内容的提问来源于stack exchange,提问作者tajgel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:52:45