React新手求助:点击宝可梦按钮展示对应详细信息
实现点击宝可梦按钮展示详情的完整方案
原代码存在的问题
- 按钮点击事件绑定错误:
onClick={handleClick(el)}会导致组件渲染时立即执行函数,而非点击时触发 handleClick未接收点击的宝可梦数据参数,无法更新对应详情- State结构限制:仅存储name和desc,无法展示更多宝可梦属性
- 缺少详情展示的UI区域
完整修改后的代码(PokeList.js)
import { Data } from "./Data"; import "./PokeList.css"; import { useState } from "react"; function PokeList() { // 初始设为null,方便判断是否选中宝可梦 const [selectedPokemon, setSelectedPokemon] = useState(null); // 接收点击的宝可梦对象,更新state const handleClick = (pokemon) => { setSelectedPokemon(pokemon); }; return ( <div className="app-container"> <div className="pokemon-container"> {/* 宝可梦按钮列表 */} <div className="all-container"> {Data.map((pokemon) => ( // 每个按钮需要唯一key,用id避免警告 <button key={pokemon.id} onClick={() => handleClick(pokemon)} className="pokemon-btn" > {pokemon.name} </button> ))} </div> {/* 宝可梦详情展示区域 */} <div className="pokemon-detail"> {selectedPokemon ? ( <div className="detail-card"> <h2>{selectedPokemon.name}</h2> {/* 图片存在时渲染,否则显示占位文字 */} {selectedPokemon.imageUrl ? ( <img src={selectedPokemon.imageUrl} alt={selectedPokemon.name} className="pokemon-img" /> ) : ( <p>暂无图片</p> )} <p>{selectedPokemon.desc}</p> <div className="stats"> <p>身高:{selectedPokemon.Height}</p> <p>体重:{selectedPokemon.Weight}</p> <h3>基础属性</h3> <ul> <li>HP: {selectedPokemon.Stat.hp}</li> <li>攻击: {selectedPokemon.Stat.attack}</li> <li>防御: {selectedPokemon.Stat.defense}</li> <li>特攻: {selectedPokemon.Stat.special_attack}</li> <li>特防: {selectedPokemon.Stat.special_defense}</li> <li>速度: {selectedPokemon.Stat.speed}</li> </ul> </div> </div> ) : ( <p>点击上方宝可梦按钮查看详情</p> )} </div> </div> </div> ); } export default PokeList;
关键修改说明
- State优化:将
pokeInfo改为selectedPokemon,初始值设为null,便于判断是否有选中的宝可梦,同时存储完整的宝可梦对象,方便后续展示所有属性。 - 点击事件修复:使用
onClick={() => handleClick(pokemon)},确保只有点击按钮时才会触发函数,并传入当前宝可梦的完整数据。 - handleClick函数完善:直接将传入的宝可梦对象存入state,无需手动解构属性,简化逻辑。
- 添加详情UI:根据
selectedPokemon是否存在,条件渲染详情卡片,包含图片、描述、身高体重及所有属性值;图片做了存在性判断,避免空图片加载错误。 - 添加key属性:map循环渲染按钮时添加
key={pokemon.id},符合React列表渲染规范,避免控制台警告。
可选样式参考(PokeList.css)
.app-container { max-width: 1200px; margin: 0 auto; padding: 20px; } .pokemon-container { display: flex; gap: 30px; flex-wrap: wrap; } .all-container { display: flex; flex-direction: column; gap: 10px; } .pokemon-btn { padding: 10px 15px; border: none; border-radius: 5px; background: #ffcb05; color: #2a75bb; font-weight: bold; cursor: pointer; transition: background 0.2s; } .pokemon-btn:hover { background: #ffb700; } .pokemon-detail { flex: 1; min-width: 300px; } .detail-card { border: 2px solid #2a75bb; border-radius: 8px; padding: 20px; background: #f8f8f8; } .pokemon-img { width: 150px; height: 150px; object-fit: contain; } .stats ul { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
内容的提问来源于stack exchange,提问作者GreatGig
相关产品推荐
相关产品推荐

