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

React状态数组已更新,但仅渲染数组中第一个对象问题求助

问题分析与解决方案

Hey there! I see the issue you're facing—only the first Fire-type Pokémon is rendering, right? This boils down to how you're handling asynchronous requests and state updates in React. Let's walk through what's going wrong and how to fix it:

核心问题

You’re updating the component state immediately after each individual Pokémon detail request finishes. Since these AJAX calls are asynchronous, they complete in an unpredictable order, and each setState triggers a re-render before all data is ready. Additionally, React’s setState is asynchronous under the hood, so frequent, scattered state updates can lead to incomplete or overwritten state values.

Another small issue: you added a key prop to the <table> inside your PokemonRow component, which is unnecessary. The key should only be applied to the top-level element being looped over (the <PokemonRow> itself in your App component).

Fixed Code

Updated App Component

We’ll convert each AJAX request to a Promise, wait for all requests to finish with Promise.all, then update the state once with all the Pokémon data:

import React, { Component } from 'react';
import './App.css';
import PokemonRow from './PokemonRow.js'

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {rows: []};
    this.performSearch()
  }

  performSearch() {
    const urlString = "http://pokeapi.salestock.net/api/v2/type/fire/";
    
    // Use native fetch instead of jQuery for cleaner React practice
    fetch(urlString)
      .then(response => response.json())
      .then(searchResults => {
        console.log("Fetched Data Successfully");
        console.log(searchResults);
        const pokemonOfType = searchResults.pokemon;
        
        // Convert each detail request into a Promise
        const pokemonDetailPromises = pokemonOfType.map(pokemon => {
          return fetch(pokemon.pokemon.url).then(res => res.json());
        });
        
        // Wait for all detail requests to complete
        Promise.all(pokemonDetailPromises)
          .then(fullPokemonList => {
            // Generate all PokemonRow components at once
            const pokemonRows = fullPokemonList.map(pokemon => (
              <PokemonRow key={pokemon.id} pokemon={pokemon} />
            ));
            // Update state once with all data
            this.setState({ rows: pokemonRows });
            console.log(`Total Fire-type Pokémon loaded: ${pokemonRows.length}`);
          })
          .catch(err => console.error("Failed to fetch Pokémon details:", err));
      })
      .catch(err => console.error("Failed to fetch type data:", err));
  }

  render() {
    return (
      <div className="App">
        <table className="titleBar">
          {/* Fixed typo: <tb> → <tbody> */}
          <tbody>
            <tr>
              <td>
                <img width="50" src="pokemon.png" alt="Pokemon logo"/>
              </td>
              <td> Pokemon Information </td>
            </tr>
          </tbody>
        </table>
        <input className="searchBar" placeholder="Enter Pokemon Name" />
        {this.state.rows}
      </div>
    );
  }
}

export default App;

Updated PokemonRow Component (Removed Unnecessary Key)

import React from 'react'

class PokemonRow extends React.Component {
  render() {
    return (
      <table>
        <tbody>
          <tr>
            <td> {this.props.pokemon.name} </td>
          </tr>
          <tr>
            <td>
              <img alt="pokemon_image" width="120" src={this.props.pokemon.sprites.front_default} />
            </td>
            <td>
              <h3>Stats</h3>
              <p>Height: {this.props.pokemon.height} ft</p>
              <p>Weight: {this.props.pokemon.weight} lbs</p>
            </td>
          </tr>
        </tbody>
      </table>
    );
  }
}

export default PokemonRow;

Why This Works

  1. Promise.all for Async Coordination: This ensures we don’t update state until every Pokémon’s detail data has been fetched, so we render all results at once instead of partial batches.
  2. Native Fetch API: Eliminates the need for jQuery, aligning with modern React project practices.
  3. Single State Update: Only one setState call triggers a single re-render, which is more efficient and avoids state inconsistencies.
  4. Fixed HTML Typo: Corrected <tb> to <tbody> for valid table structure.

With these changes, all Fire-type Pokémon should render correctly on your page!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:34:41