【问题标题】:PokeAPI - Fetching Pokemon DataPokeAPI - 获取口袋妖怪数据
【发布时间】:2020-09-18 10:52:11
【问题描述】:

我刚刚开始学习 React,并且正在尝试使用 PokeAPI 构建 PokeDex,但我很难理解如何从 API 中获取数据。我想获取前 384 个 Pokemon 相关信息。我在下面的 componentDidMount() 中编写了这段代码,以提取我的主 App 类组件中的完整数据,并将其推送到一个名为 pokemonArray 的数组中,我将设置为我的状态。

let pokemonArray = [];
/* First API fetch call to return names and URL's of first 384 Pokemon after promise is resolved.*/
fetch('https://pokeapi.co/api/v2/pokemon/?limit=384')
  .then(response => response.json())
  .then(data => {
    let results = data.results;
    let promisesArray = results.map(result => {
      return fetch(result.url).then(response => response.json()).then(data => pokemonArray.push(data));
    })
    return Promise.all(promisesArray)
  }).then(this.setState({ pokemon: pokemonArray }, () => console.log('Main Pokemon State: ', this.state.pokemon)));

}

在我的渲染方法中,我想将这个新设置的状态作为道具传递给一个名为 PokeList 的组件,就像这样

<PokeList pokemon={this.state.pokemon} />

一旦我传递它并尝试像这样在我的 PokeList 组件中呈现它

export const PokeList = ({ pokemon }) => {
    console.log(pokemon);

    return (
        <div className="pokecard-container">
            <h1>{pokemon[0].id}</h1>
        </div>
    );
}

我收到一条错误消息,提示 TypeError: Cannot read property '0' of null。 React Developer 工具显示了使用检索到的值填充的状态以及正在设置的道具,但它似乎认为它为空。谁能帮忙解决这个问题,看到这个错误真是令人沮丧

【问题讨论】:

  • 你的应用没有pokemon数组;它必须等待获取,因此您需要在 pokemon 加载之前为 pokemon 和初始行为提供初始值
  • 谢谢,有一个条件有助于防止它再次出错

标签: javascript html css reactjs frontend


【解决方案1】:

您的代码存在两个问题。首先,这是一个修改后的工作版本:

fetch('https://pokeapi.co/api/v2/pokemon/?limit=2')
  .then(response => response.json())
  .then(data => {
    let results = data.results;
    let promisesArray = results.map(result => {
      return fetch(result.url).then(response => response.json());
    })
    return Promise.all(promisesArray);
  }).then((data) => this.setState({ pokemon: data }, () => console.log('Main Pokemon State: ', this.state.pokemon)));

以及解释:

问题 1:

原码:

let promisesArray = results.map(result => {
  return fetch(result.url).then(response => response.json()).then(data => pokemonArray.push(data));
})
return Promise.all(promisesArray)

最后一个then() 回调返回pokemonArray.push(data) 的结果。 Array.push 返回数组的长度,所以return Promise.all(promisesArray) 返回一个数组长度的数组。

改成:

let promisesArray = results.map(result => {
  return fetch(result.url).then(response => response.json()); // Returns the data
})
return Promise.all(promisesArray)

问题 2:

原码:

then(this.setState({ pokemon: pokemonArray }, () => console.log('Main Pokemon State: ', this.state.pokemon)));

您必须向then() 提供回调函数:

.then((data) => this.setState({ pokemon: data }, () => console.log('Main Pokemon State: ', this.state.pokemon)));

您还必须记住在创建组件时初始化状态:

constructor(props) {
  super(props);

  this.state = {
    pokemon: [],
  };
}

因此,当您渲染 PokeList (&lt;PokeList pokemon={this.state.pokemon} /&gt;) 时,它总是会收到一个数组,尽管在获取数据之前它是空的。

【讨论】:

  • 非常感谢这些更改,您的解释帮助我更好地理解了 fetch API 和 Promises 本身。我已经进行了更改,并设置了一个显示

    Loading

    的条件,以防止它出错,但它卡在该条件下并且根本没有获取值跨度>
  • 这是我的 PokeList 组件代码,对于获取的数据中的每个条目,它将映射一个新的口袋妖怪组件 export const PokeList = ({ pokemonData }) =&gt; { console.log('Pokemon Data prop: ', pokemonData); if (pokemonData === undefined) { return ( &lt;h1&gt;Loading Pokemon...&lt;/h1&gt; ); } return ( &lt;div className="pokecard-container"&gt; {pokemonData.map(pokemon =&gt; &lt;Pokemon name={pokemon.name} sprite={pokemon.sprites.front_default} /&gt;)} &lt;/div&gt; ); }
  • 这是我的口袋妖怪组件代码,它在 PokeList 容器 export const Pokemon = ({ name, sprite }) =&gt; { return ( &lt;div className="poke-card"&gt; &lt;img alt="Pokemon sprite" src={sprite} /&gt; &lt;h3&gt;{name}&lt;/h3&gt; &lt;/div&gt; ); } 上呈现卡片状组件
  • 这是一个工作示例,其中包含我的答案中的代码以及您更新的代码:codesandbox.io/s/62110181-9u6sl 请注意,我已更改状态变量的名称 (this.state.pokemons)
  • 我发现了问题!我发现我传递给 PokeList 的道具与我在 PokeList 组件中解构出来的道具变量不同。现在可以了!非常感谢您对此的帮助。我已经对答案投了赞成票,但 StackOverflow 说它不可见,因为我还是一个新手用户 :)
【解决方案2】:

这是我重写您的获取代码的建议:

class App extends Component{
 state = {
   pokemonArray : []
 }
 componentDidMount = () =>{
   fetch('https://pokeapi.co/api/v2/pokemon/?limit=384')
   .then(response => response.json())
   .then(data => {
      let results = data.results;
      this.setState({ pokemonArray : [...results]})
     console.log("Here are my pokemons",   this.state.pokemonArray)
     })


 }
...
}

我正在使用扩展运算符将接收到的数据复制到 pokemonArray。您可以将您的数组作为道具传递给组件。 希望对您有所帮助。

【讨论】:

  • 非常感谢您的建议,我将使用Spread运算符!
猜你喜欢
  • 2016-12-30
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-10
  • 2021-11-07
  • 1970-01-01
  • 2021-03-24
相关资源
最近更新 更多