Pokemon API Uncaught TypeError: Невозможно прочитать свойство '0' из неопределенного - PullRequest
2 голосов
/ 13 января 2020

Я пытаюсь получить доступ к способностям моего покемона, но продолжаю получать ту же ошибку. Я использую React-хуки для создания своего проекта, и для данных, которые я извлек из Pokemon API, было установлено значение setWildPokemon. Если я поставлю wildPokemon.name, я получу имя покемона, что нормально image. Это также работает, когда я вывожу wildPokemon.abilities. Однако, когда я начинаю углубляться в свои вложенные объекты, именно тогда вещи gohaywire

code description

function App() {
  const [pokedex, setPokedex] = useState([]);
  const [wildPokemon, setWildPokemon] = useState({});
  const [storeCard, setStoreCard] = useState({});

  const { id, sprites } = wildPokemon;
  // console.log(id, sprites.back_shiny);
  console.log(wildPokemon);
  console.log(wildPokemon.name);
  // console.log(wildPokemon.types[0].name);

  useEffect(() => {
    encounterWildPokemon();
  }, []);

  const pokeId = () => {
    const min = Math.ceil(1);
    const max = Math.floor(151);
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };


  const encounterWildPokemon = () => {
    axios
      .get(`https://pokeapi.co/api/v2/pokemon/${pokeId()}`)
      .then(response => {
        setWildPokemon(response.data);
      });
  };

  const catchPokemon = pokemon => {
    setPokedex(state => {
      const monExists = state.filter(p => pokemon.id === p.id).length > 0; // mostly false. Only true if you catch the same pokemon
      if (!monExists) {
        state = [...state, pokemon];
        state.sort(function(a, b) {
          return a.id - b.id;
        });
      }
      return state;
    });
    encounterWildPokemon(); // MISTAKE: we have to call this function whenever we're done
  };

  const releasePokemon = id => {
    setPokedex(state => state.filter(p => p.id != id));
  };

  // PokeModal
  const [show, setShow] = useState(false);

  const handleClose = () => setShow(false);
  const handleShow = pokemon => {
    setShow(true);
    setStoreCard(pokemon);
  };

  // JSX
  return (
    <div className="app-wrapper container">
      <header>
        <h1 className="title">React Hooks</h1>
        {/* <img src="{sprites[0].back_default}" /> */}
        <h3 className="subtitle">With Pokémon</h3>
      </header>
      <section className="wild-pokemon">
        <h2>Wild Encounter</h2>
        <img
          src={
            "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/" +
            wildPokemon.id +
            ".png"
          }
          className="sprite"
          alt=""
        />
        <h3>{wildPokemon.name}</h3>
        <button className="catch-btn" onClick={() => catchPokemon(wildPokemon)}>
          CATCH
        </button>
      </section>

ОБНОВЛЕНО: Хорошо, я только что решил проблему =) , Я пытался получить доступ к данным, как только веб-страница отображается. Поскольку выборка выполняется асинхронно, я в основном пытался получить данные, которых еще не было, которые являются пустым объектом.

1 Ответ

1 голос
/ 13 января 2020

Состояние - это пустой объект при начальной загрузке, и это то, что используется для первого рендера. Когда вы пытаетесь получить доступ к sprites[0], спрайты равны undefined, так как данные еще не были загружены. Одним из способов решения этой проблемы является задержка рендеринга до получения данных:

 return (
  sprites && sprites.length && (
    <div className="app-wrapper container">
      <header>
        <h1 className="title">React Hooks</h1>
        <img src={sprites[0].back_default} />
        <h3 className="subtitle">With Pokémon</h3>
      </header>
   ...    
  )

В качестве альтернативы вы можете использовать состояние loading и устанавливать его на true до тех пор, пока данные не будут выбраны. Полезно, когда вы хотите показать загрузчик.

const [loading, setLoading] = useState(true);

const encounterWildPokemon = () => {
    setLoading(true); 
    axios
      .get(`https://pokeapi.co/api/v2/pokemon/${pokeId()}`)
      .then(response => {
        setWildPokemon(response.data);
        setLoading(false);
      });
  };


// JSX
return (
  loading ? <p>Loading...</p> : (
    <div className="app-wrapper container">
      <header>
        <h1 className="title">React Hooks</h1>
        <img src={sprites[0].back_default} />
        <h3 className="subtitle">With Pokémon</h3>
      </header>
   ...    
  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...