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

React使用PokeAPI按ID实现宝可梦地区筛选 兼容类型筛选与分页

宝可梦图鉴地区筛选功能实现方案

你原本的ID区间匹配思路完全可行,只需要对现有数据拉取逻辑做少量修改即可,同时可以兼容现有类型筛选、分页功能,具体实现步骤如下:

前置准备

首先维护一份地区和对应宝可梦ID区间的映射表,覆盖所有主线世代即可:

const REGION_ID_RANGE = {
  all: { start: 1, end: 1025 }, // 全国图鉴默认覆盖到帕底亚世代
  kanto: { start: 1, end: 151 },
  johto: { start: 152, end: 251 },
  hoenn: { start: 252, end: 386 },
  sinnoh: { start: 387, end: 493 },
  unova: { start: 494, end: 649 },
  kalos: { start: 650, end: 721 },
  alola: { start: 722, end: 809 },
  galar: { start: 810, end: 898 },
  paldea: { start: 899, end: 1025 }
};

新增一个selectedRegion状态存储当前选中的地区,默认值设为all;同时在地区、类型筛选器的change事件里,把分页页码page重置为0,避免出现页码越界问题。

核心拉取逻辑修改

你原有代码存在一个小bug:每页拉取24条数据,但总页数计算时按25条/页做除法,会导致尾页数据异常,统一按24条/页计算即可。修改后的完整拉取函数如下:

const PAGE_SIZE = 24;
const fetchPokemon = async () => {
  try {
    setLoading(true);
    const selectType = selectedType.toLowerCase();
    const { start: regionStart, end: regionEnd } = REGION_ID_RANGE[selectedRegion];
    const regionTotal = regionEnd - regionStart + 1;

    if (selectType === "all") {
      // 计算当前页在地区区间内的偏移量和拉取数量,避免跨地区拉取
      const offset = regionStart - 1 + PAGE_SIZE * page;
      // 偏移量超过地区最大ID时直接返回空
      if (offset >= regionEnd) {
        setPokemon([]);
        setTotal(0);
        setNotFound(true);
        setLoading(false);
        return;
      }
      // 最后一页不足24条时自动截断limit
      const limit = Math.min(PAGE_SIZE, regionEnd - offset);
      const data = await getPokemon(limit, offset);
      const promises = data.results.map(async (pokemon) => {
        return await getPokemonData(pokemon.url);
      });
      const results = await Promise.all(promises);
      setPokemon(results);
      setTotal(Math.ceil(regionTotal / PAGE_SIZE));
      setNotFound(results.length === 0);
    } else {
      // 类型筛选分支:先拉取全量该类型宝可梦,再按地区ID过滤
      const { data: typePokemonList } = await searchPokemonByType(
        selectType,
        9999, // 拉取该类型全量数据,type接口单类型返回数据量峰值不超过200条,无性能压力
        0
      );
      // 过滤出当前地区区间内的宝可梦,从url中提取宝可梦ID做判断
      const regionFilteredList = typePokemonList.filter(item => {
        const pokemonId = Number(item.pokemon.url.split('/').filter(Boolean).pop());
        return pokemonId >= regionStart && pokemonId <= regionEnd;
      });
      // 对过滤后的数据做前端分页
      const pageStart = PAGE_SIZE * page;
      const pageData = regionFilteredList.slice(pageStart, pageStart + PAGE_SIZE);
      const promises = pageData.map(async (pokemon) => {
        return await getPokemonData(pokemon.pokemon.url);
      });
      const results = await Promise.all(promises);
      setPokemon(results);
      setTotal(Math.ceil(regionFilteredList.length / PAGE_SIZE));
      setNotFound(results.length === 0);
    }
    setLoading(false);
  } catch (err) {
    setLoading(false);
    setNotFound(true);
  }
};

可选优化方案

如果不想硬编码ID区间,可以在应用初始化时调用PokeAPI的世代接口拉取每个世代对应的宝可梦列表,提取ID后动态生成REGION_ID_RANGE映射表,后续官方更新世代时不需要手动修改硬编码值。但对于个人项目来说,硬编码的方式性能更好,不需要额外的首屏请求,完全够用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:01:40