尝试使用 API 创建口袋妖怪搜索,但遇到数据未按时加载的问题

Posted

技术标签:

【中文标题】尝试使用 API 创建口袋妖怪搜索,但遇到数据未按时加载的问题【英文标题】:Trying to create a pokemon search using API but running into issue where data is not being loaded on time 【发布时间】:2021-06-11 15:11:11 【问题描述】:

我正在尝试在这里使用 pokemon api 创建一个 pokemon 搜索应用程序 - https://pokeapi.co/ 我收到“无法读取未定义的属性‘物种’”的错误。 这是我应该使用useEffect的地方吗? 我猜这与我没有使用 async / await 功能有关,但我想先问一下它是否可能是别的东西。

这是我的代码

import  useState, useEffect  from "react";
import "./App.css";
function App() 
const [pokemonName, setPokemonName] = useState("ditto");
const [chosen, setChosen] = useState(false);
const [pokemonData, setPokemonData] = useState(
name: "",
species: "",
img: "",
hp: "",
attack: "",
defense: "",
type: "",
);

const searchPokemon = () => 
const response = fetch(
  `https://pokeapi.co/api/v2/pokemon/$pokemonName`
).then((response) => 
  setPokemonData(
    name: pokemonName,
    species: response.data.species.name,
    img: response.data.sprites.front_default,
    hp: response.data.stats[0].base.stat,
    attack: response.data.stats[1].base.stat,
    defense: response.data.stats[3].base.stat,
    type: response.data.types[0].type.name,
  );
  setChosen(true);
);
console.log(response);
;

return (
<div className="App">
  <input
    className="border-b-2 border-black px-4"
    type="text"
    onChange=(e) => 
      setPokemonName(e.target.value);
    
  />
  <button
    className="rounded text-white bg-blue-500 p-2 text-sm"
    onClick=searchPokemon
  >
    Search Pokemon
  </button>

  <div>
    !chosen ? (
      <h1>Please choose a pokemon</h1>
    ) : (
      <>
        <h1>pokemonData.name</h1>
        <img src=pokemonData.img alt=pokemonData.name />
        <h2>pokemonData.species</h2>
        <h2>pokemonData.type</h2>
        <h2>pokemonData.hp</h2>
        <h2>pokemonData.attack</h2>
        <h2>pokemonData.defense</h2>
      </>
    )
  </div>
</div>
);


export default App;

【问题讨论】:

***.com/questions/14220321/… 对 react 不太熟悉,但您可能应该使用 useEffect 在数据加载后更改 DOM 值。 哪一行会引发错误? 【参考方案1】:

你忘记在获取后做 response.json() 以获取 json 格式的正文,并且数据形状有一些错误(响应不在“数据”属性下)

在这里查看修改后的工作版本:https://codesandbox.io/s/keen-***-8egfe?file=/src/App.js

【讨论】:

【参考方案2】:

您没有将响应转换为.json(),并且在解析响应时还添加了.data,这不是必需的。另外,你base.stat应该是base_state

const  useState, useEffect  = React;

function App() 
  const [pokemonName, setPokemonName] = useState("ditto");
  const [chosen, setChosen] = useState(false);
  const [pokemonData, setPokemonData] = useState(
    name: "",
    species: "",
    img: "",
    hp: "",
    attack: "",
    defense: "",
    type: "",
  );

  const searchPokemon = () => 
    const response = fetch(
    `https://pokeapi.co/api/v2/pokemon/$pokemonName`
    )
    .then(response => response.json())
    .then(response => 
      setPokemonData(
        name: pokemonName,
        species: response.species.name,
        img: response.sprites.front_default,
        hp: response.stats[0].base_stat,
        attack: response.stats[1].base_stat,
        defense: response.stats[3].base_stat,
        type: response.types[0].type.name,
      );
      setChosen(true);
    );
  ;
  
  return (
    <div className="App">
      <input
        className="border-b-2 border-black px-4"
        type="text"
        onChange=(e) => 
          setPokemonName(e.target.value);
        
      />
      <button
        className="rounded text-white bg-blue-500 p-2 text-sm"
        onClick=searchPokemon
      >
        Search Pokemon
      </button>

      <div>
        !chosen ? (
          <h1>Please choose a pokemon</h1>
        ) : (
          <React.Fragment>
            <h1>pokemonData.name</h1>
            <img src=pokemonData.img alt=pokemonData.name />
            <h2>pokemonData.species</h2>
            <h2>pokemonData.type</h2>
            <h2>pokemonData.hp</h2>
            <h2>pokemonData.attack</h2>
            <h2>pokemonData.defense</h2>
          </React.Fragment>
        )
      </div>
    </div>
  );


ReactDOM.render(
  <App />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

【讨论】:

【参考方案3】:

尝试创建一个函数来从 API 中获取数据。像这样的

function getPokemonData() 
    fetch('https://pokeapi.co/api/v2/pokemon/')
        .then((response) => response.json())
        .then((response) =>
            setPokemonData(
                name: pokemonName,
                species: response.data.species.name,
                img: response.data.sprites.front_default,
                hp: response.data.stats[0].base.stat,
                attack: response.data.stats[1].base.stat,
                defense: response.data.stats[3].base.stat,
                type: response.data.types[0].type.name,
            )
        );


然后在componentDidMount

里面调用这个函数
componentDidMount()
   this.getPokemonData();

【讨论】:

以上是关于尝试使用 API 创建口袋妖怪搜索,但遇到数据未按时加载的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 .NET 中反序列化 Pokemon API

如何解析这个 JSON 口袋妖怪字典?口袋妖怪 API (swift 3)

使用 jQuery 将值发布到 api 未按预期工作

我的音频和搜索功能未按预期运行

无法从异步函数获取返回值,等待未按预期工作(Vue API 服务)

Node Js Async 未按正确顺序运行并跳过承诺