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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:17:40