React类组件与Props求助:新手构建宝可梦列表及详情页
宝可梦应用实现指南(React新手向)
嘿,作为React新手能搭出这个基础框架已经超棒啦!我来帮你把这个宝可梦应用完善起来,实现「20个宝可梦列表+点击查看详情」的核心功能~
第一步:补全组件结构并添加状态管理
首先,咱们需要在父组件App里管理全局状态:宝可梦列表数据和当前选中的宝可梦。然后通过props把数据和交互方法传递给子组件。
完整的App组件代码
import React, { Component } from 'react'; import './styles/App.css'; class App extends Component { // 初始化状态:空的宝可梦列表 + 未选中任何宝可梦 state = { pokemons: [], selectedPokemon: null }; // 组件挂载后获取宝可梦数据 componentDidMount() { // 从PokéAPI获取前20个宝可梦的基础数据 fetch('https://pokeapi.co/api/v2/pokemon?limit=20') .then(res => res.json()) .then(data => { // 对每个宝可梦,再请求完整详情数据(比如图片、属性) Promise.all(data.results.map(pokemon => fetch(pokemon.url).then(res => res.json()) )).then(detailedPokemons => { this.setState({ pokemons: detailedPokemons }); }); }); } // 处理宝可梦点击事件:更新选中的宝可梦 handlePokemonClick = (pokemon) => { this.setState({ selectedPokemon: pokemon }); }; render() { const { pokemons, selectedPokemon } = this.state; return ( <div className="App"> <h1>Pokedex!</h1> <div className="pokedex-container"> <PokemonList pokemons={pokemons} onPokemonClick={this.handlePokemonClick} /> <PokemonDetail pokemon={selectedPokemon} /> </div> </div> ); } }
第二步:实现PokemonList和Pokemon列表项组件
PokemonList负责渲染所有宝可梦列表,Pokemon是单个列表项,绑定点击事件来触发详情切换。
// Pokemon列表容器组件 class PokemonList extends Component { render() { const { pokemons, onPokemonClick } = this.props; if (pokemons.length === 0) { return <div className="loading">加载中...</div>; } return ( <div className="pokemon-list"> {pokemons.map(pokemon => ( <Pokemon key={pokemon.id} pokemon={pokemon} onClick={() => onPokemonClick(pokemon)} /> ))} </div> ); } } // 单个宝可梦列表项组件 class Pokemon extends Component { render() { const { pokemon, onClick } = this.props; // 把宝可梦名称首字母大写 const capitalizedName = pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1); return ( <div className="pokemon-item" onClick={onClick}> <img src={pokemon.sprites.front_default} alt={capitalizedName} className="pokemon-thumbnail" /> <p>{capitalizedName}</p> </div> ); } }
第三步:实现PokemonDetail详情组件
这个组件会根据选中的宝可梦展示详情,如果没有选中任何宝可梦则显示提示文案。
// 宝可梦详情组件 class PokemonDetail extends Component { render() { const { pokemon } = this.props; if (!pokemon) { return <div className="detail-empty">请选择一个宝可梦查看详情</div>; } const capitalizedName = pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1); // 整理属性为逗号分隔的字符串 const types = pokemon.types.map(type => type.type.name).join(', '); return ( <div className="pokemon-detail"> <h2>{capitalizedName}</h2> <img src={pokemon.sprites.other['official-artwork'].front_default} alt={capitalizedName} className="pokemon-detail-image" /> <div className="pokemon-info"> <p><strong>身高:</strong> {pokemon.height / 10} m</p> <p><strong>体重:</strong> {pokemon.weight / 10} kg</p> <p><strong>属性:</strong> {types}</p> </div> </div> ); } }
第四步:添加基础样式(App.css)
给应用加一些基础布局和样式,让列表和详情页更美观:
.App { max-width: 1200px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif; } .pokedex-container { display: flex; gap: 30px; margin-top: 20px; } .pokemon-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; flex: 1; } .pokemon-item { border: 1px solid #e0e0e0; border-radius: 8px; padding: 10px; text-align: center; cursor: pointer; transition: background-color 0.2s; } .pokemon-item:hover { background-color: #f5f5f5; } .pokemon-thumbnail { width: 80px; height: 80px; } .pokemon-detail { flex: 1; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; text-align: center; } .pokemon-detail-image { width: 200px; height: 200px; margin: 20px 0; } .detail-empty { flex: 1; display: flex; align-items: center; justify-content: center; border: 1px dashed #ccc; border-radius: 8px; color: #666; } .loading { text-align: center; font-size: 18px; color: #666; margin-top: 20px; }
关键知识点小提示
- 状态提升:把选中的宝可梦状态放在父组件
App里,这样列表和详情组件能共享状态,是React组件通信的常用方式。 - 批量数据获取:用
Promise.all批量请求宝可梦详情,确保所有数据加载完成后再更新页面状态。 - props传递:子组件通过props接收数据和回调函数,实现父子组件的交互逻辑。
这样你就能得到一个完整可运行的宝可梦应用啦,点击列表里的宝可梦就能在右侧看到它的详细信息~
内容的提问来源于stack exchange,提问作者Rihards Repels
相关产品推荐
相关产品推荐

