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

React+JavaScript构建Pokedex:单选框筛选与搜索栏问题求助

Pokedex 开发问题解决方案

问题1:世代单选框与apiGeneration字段关联

你的单选框值是"1G"、"2G"这类格式,而API返回的apiGeneration是数字类型(比如1、2),只需在筛选逻辑里做格式转换即可关联:

  • 在filter函数中,若有选中的单选框,提取其值的数字部分(比如"1G"取1),和pokemon.apiGeneration对比;
  • 未选中时直接返回true,显示全部宝可梦。

问题2:搜索栏实现(替代DOM事件监听)

React中推荐用受控组件实现输入交互,无需手动添加addEventListener:

  • 新增searchTerm状态存储搜索内容;
  • 给搜索框绑定value和onChange,实时更新状态;
  • 在筛选逻辑里匹配宝可梦名称与搜索关键词。

修改后的完整代码

import axios from "axios";
import React, { useEffect, useState } from "react";
import Card from "./Card";

const Pokedex = () => {
  const [data, setData] = useState([]);
  const radios = ["1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G"];
  const [selectedRadio, setSelectedRadio] = useState("");
  // 新增搜索状态
  const [searchTerm, setSearchTerm] = useState("");

  useEffect(() => {
    axios
      .get("https://pokebuildapi.fr/api/v1/pokemon")
      .then((res) => setData(res.data));
  }, []);

  return (
    <div className="pokemons">
      <h2 id="search-title">Pokedex</h2>
      <p className="search-text">Recherhe par nom</p>
      <div>
        {/* 受控搜索框 */}
        <input
          type="search"
          id="search-bar"
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value.toLowerCase())}
          placeholder="输入宝可梦名称..."
        />
      </div>

      <div className="gen-search">
        {radios.map((generation) => (
          // 用generation作为唯一key,替代index
          <ul className="radio-container" key={generation}>
            <li>
              <input
                type="radio"
                id={generation}
                name="generationRadio"
                checked={generation === selectedRadio}
                onChange={(e) => setSelectedRadio(e.target.id)}
              />
              <label htmlFor={generation}>{generation}</label>
            </li>
          </ul>
        ))}
      </div>
      {selectedRadio && (
        <button onClick={() => setSelectedRadio("")}>
          Annuler la recherche
        </button>
      )}
      <div className="pokemon-container">
        <ul>
          {data
            .filter((pokemon) => {
              // 世代筛选逻辑
              const matchesGeneration = selectedRadio 
                ? pokemon.apiGeneration === Number(selectedRadio[0]) 
                : true;
              // 名称搜索逻辑(不区分大小写)
              const matchesSearch = pokemon.name.toLowerCase().includes(searchTerm);
              // 同时满足两个筛选条件
              return matchesGeneration && matchesSearch;
            })
            .map((pokemon) => (
              // 用pokemon.id作为key,比index更稳定
              <Card key={pokemon.id} pokemon={pokemon} />
            ))}
        </ul>
      </div>
    </div>
  );
};

export default Pokedex;

关键优化说明

  1. 世代匹配:通过selectedRadio[0]提取数字部分,转成数字后与apiGeneration对比;
  2. 搜索体验:将输入和名称统一转为小写,实现不区分大小写的搜索;
  3. 组件稳定性:把map的key从index替换为唯一标识(generation/pokemon.id),避免不必要的组件重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:32:21