【问题标题】:while trying to fetch data,i get "Unhandled Rejection (TypeError): undefined is not iterable"在尝试获取数据时,我得到“未处理的拒绝(TypeError):未定义不可迭代”
【发布时间】:2021-02-27 05:38:19
【问题描述】:

我对此很菜鸟,所以我想做的是获取 pokeapi.co (pokemon api) 的数据,所以我得到一个包含对象的数组,每个对象都有一个 url,这个 url 你可以获取它并获取有关当前口袋妖怪的所有信息...它工作正常,直到我尝试将数组与内部的所有对象映射并显示以下错误...(我尝试使用 async/await 但不知道如何使用它...帮助!)

import Card from "./card"
import React,{useState,useEffect} from "react"

function App() {

const [pokemon,setPokemon]=useState()
const[loading,setLoading]=useState(true)

useEffect(
 async ()=>{
    
        return await fetch("https://pokeapi.co/api/v2/ability/?limit=20&offset=20")
      .then(res=> res.json())
      .then( async data=>{return await data.results.map(async element=>{return await fetch(element.url).then(res=>res.json()).then(data=>{return setPokemon(prevState=>{return [...prevState,{data}]})})})})}
    
,[])
 
  return (
    <div className="App">
      <header id="header" className="py-10 w-full bg-yellow-500">
        <h1 className="text-4xl text-center font-bold text-red-700">Pokedex.</h1>
      </header>

     {loading &&  <div class="rounded-t-lg overflow-hidden border-t border-l border-r  text-center p-4 py-12">
        <span class="inline-flex rounded-md shadow-sm">
          <button type="button" class="inline-flex items-center px-4 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150 cursor-not-allowed" disabled="">
            <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
              <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
              <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
            Processing
          </button>
        </span>
        </div>}
    
      <div className="grid grid-cols-4 gap-4 my-10  px-10">
         {pokemon? pokemon.results.map((element,index)=>{return <Card key={index} name={ element.name.toUpperCase()} />}):null} 
      </div>
        <footer className="text-center text-gray-500 font-bold">2020</footer>
    </div>
  );
}
export default App;

当我拿到这个(https://pokeapi.co/api/v2/ability/?limit=20&offset=20) 我得到这个 所以我尝试获取对象内的每个 url 以获取有关当前 pokemon 的所有信息,所以响应是这样的 我想要做的是将这些数据保存在状态中以便以后呈现它

我迷失在使用 async/await...

【问题讨论】:

  • 混合await.then() 回调只会导致代码混乱。坚持一个约定
  • 看起来错误是说您的 pokemon 状态值不可迭代,因此无法传播。请更新您的问题以包含Minimal, Complete, and Reproducible 组件代码示例。我同意@Phil,async/await 看起来完全是多余的,因为效果 never 处理等待的返回值。
  • await data.results.map 没有意义,因为data.results.map 返回的是一个数组,而不是一个 Promise
  • also ... [...prevState, { data }] 意味着每次迭代都会覆盖相同的 data: 属性 - 所以,你最终会得到一个

标签: javascript reactjs fetch-api


【解决方案1】:

问题

  1. 效果挂钩回调是同步处理的,不能是async
  2. pokemon 初始状态未定义,因此不可迭代
  3. setPokemonpokemon 状态视为一个数组,但 pokemon 状态稍后会被当作一个对象来访问,即 pokemon.results
  4. 加载状态永远不会被清除
  5. 所有口袋妖怪data 都嵌套在data 键中,但访问时就像数据都在根级别,即element.name.toUpperCase()

小问题

  1. 在 JSX 中使用 classNameclass
  2. 使用驼峰式属性,即strokeWidthstroke-width

解决方案

提供初始状态,我建议一个数组。现在之前的状态是可迭代的

const [pokemon, setPokemon] = useState([]);

直接渲染数组。尽量避免使用数组索引作为反应键。

{pokemon.map((element) => <Card key={element.id} name={element.name.toUpperCase()} />)}

坚持承诺链,或异步/等待。

useEffect 使用承诺链。添加一个用于处理错误的 catch 块,以及一个用于清除加载状态的 finally 块。

useEffect(() => {
  fetch("https://pokeapi.co/api/v2/ability/?limit=20&offset=20")
    // Return response JSON object promise
    .then((res) => res.json())

    // Map array of fetch request promises
    .then((data) => Promise.all(data.results.map((el) => fetch(el.url))))

    // Map array of response JSON object promises
    .then((results) => Promise.all(results.map((res) => res.json())))

    // Update state, copy old state and append new
    .then((data) => setPokemon((pokemon) => [...pokemon, ...data]))

    .catch((error) =>
      console.error("There has been a problem with your fetch operation:", error)
    )
    .finally(() => setLoading(false));
}, []);

useEffect 使用异步/等待。将所有获取逻辑包装在 async 函数中,并在效果挂钩回调中调用 that。添加一个用于处理错误的 catch 块,以及一个用于清除加载状态的 finally 块。

useEffect(() => {
  const pokeFetch = async () => {
    try {
      const res = await fetch("https://pokeapi.co/api/v2/ability/?limit=20&offset=20");

      // Await response JSON object promise
      const data = await res.json();

      // Await map array of fetch request promises
      const urlRes = await Promise.all(data.results.map((el) => fetch(el.url)));

      // Await map array of response JSON object promise
      const results = await Promise.all(urlRes.map((res) => res.json()));

      // Update state, copy old state and append new
      setPokemon((pokemon) => [...pokemon, ...results]);
    } catch (error) {
      console.error("There has been a problem with your fetch operation:", error);
    } finally {
      setLoading(false);
    }
  };

  pokeFetch();
}, []);

JSX 渲染。使用classNamestrokeWidth 属性。无条件映射pokemonarray.prototype.map 将毫无问题地处理空数组状态。

return (
  <div className="App">
    <header id="header" className="py-10 w-full bg-yellow-500">
      <h1 className="text-4xl text-center font-bold text-red-700">
        Pokedex.
      </h1>
    </header>

    {loading && (
      <div className="rounded-t-lg overflow-hidden border-t border-l border-r  text-center p-4 py-12">
        <span className="inline-flex rounded-md shadow-sm">
          <button
            type="button"
            className="inline-flex items-center px-4 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150 cursor-not-allowed"
            disabled=""
          >
            <svg
              className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
            >
              <circle
                className="opacity-25"
                cx="12"
                cy="12"
                r="10"
                stroke="currentColor"
                strokeWidth="4"
              ></circle>
              <path
                className="opacity-75"
                fill="currentColor"
                d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
              ></path>
            </svg>
            Processing
          </button>
        </span>
      </div>
    )}

    <div className="grid grid-cols-4 gap-4 my-10  px-10">
      {pokemon.map((element) => (
        <Card key={element.id} name={element.name.toUpperCase()} />
      ))}
    </div>
    <footer className="text-center text-gray-500 font-bold">2020</footer>
  </div>
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    • 2022-01-03
    • 2023-04-06
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2017-11-20
    相关资源
    最近更新 更多