【问题标题】:React: async and await not working with fetch反应:async 和 await 不能与 fetch 一起使用
【发布时间】:2021-06-05 00:12:34
【问题描述】:

我在节点服务器上有 API 在调用时返回这样的 JSON:

{"result":[{"ProductID":1,"ProductName":"iPhone10","ProductDescription":"Latest smartphone from Apple","ProductQuantity":100}]}

我正在尝试使用带有 React 的 fetch API 向用户显示所有这些信息,但无论我的调用返回什么 undefined。这是我的反应代码:

const [products, setProducts] = useState({})

async function getProducts() {
    await fetch(`http://127.0.0.1:5000/listProducts`)
    .then(response => response.json())
    .then(response=>{
      setProducts({products:response.result})
      console.log(response.result);
      products.map(products =>
        <h1>{products.ProductName}</h1>
        <h1>{products.ProductDescription}</h1>
        )
    })
    .catch(err=>console.error(err))
  }

函数 getProducts() 在页面加载时调用一次。我做错了什么?提前致谢。

【问题讨论】:

  • 1.你需要return await fetch() 2。getProducts 仍然会产生一个承诺,所以你需要这样消费它。 await 它或使用 getProducts().then()
  • 如果 async/await 只是 fetch 调用的包装器,也绝对不需要。 function getProducts() { return fetch(...); }
  • 把它包装在 useEffect 中,不要忘记添加任何依赖项。另外,我认为您不应该将 .then 与 async/await 一起使用,如发布的答案中所述。使用其中之一。
  • 好吧,现在 JSON 已成功打印到控制台,但我收到错误“无法读取未定义的属性映射”。尝试不使用地图方法显示可能会更好?
  • 看起来您在设置状态后直接映射产品。在设置状态之前,产品将是未定义的。在期望他们在那里之前,您需要检查一下。或者,使用 useEffect。请参阅下面的示例

标签: javascript json reactjs fetch-api


【解决方案1】:

您不能将async await.then() 一起使用,您只能使用async await.then()

【讨论】:

  • 我试过不等待,问题是它不会等待响应。
  • 你绝对可以同时使用async/await.then——尽管它通常被认为是不好的风格。但这不是这里的问题,问题是fetch返回的promise缺少return
【解决方案2】:

试试这个...


 const [products, setProducts] = useState({})

  React.useEffect(() => {
    const fetchData = async () => {
      const result = await fetch('http://127.0.0.1:5000/listProducts')

        // console log here to determine how to set products
      console.log(result)
      setProducts(result)
    }

    fetchData()
  }, [])

  React.useEffect(() => {
   if (!!products) {
     // here you could access products!
    }
  }, [products])

  if (!products) return null

  return products.map((product) => (
    <>
      <h1>{products.ProductName}</h1>
      <h1>{products.ProductDescription}</h1>
    </>
  ))


【讨论】:

  • 如何调用 TestThis 函数? TestThis() 似乎不起作用
  • 这只是你所拥有的一个例子。我把它放在组件内部进行测试。就拿内容...我会更新它
  • 也谢谢你,我设法解决了:)
【解决方案3】:

你的函数做错了:

  • 名称应该是getAndSetProducts 甚至是setProducts / initProducts,因为它返回一个Promise&lt;void&gt;,因为你实际上并没有返回任何东西;
  • 您在products 中设置了一个对象{ products: Product[] },我认为您只需要Product[](产品数组),否则您必须通过products.products 获得产品;
  • 地图没用,因为你不对地图响应做任何事情,加上地图中的变量products 会覆盖导入的变量(以后可能会导致一些错误)。

尝试做:

const [products, setProducts] = useState([]); // Array instead of object

async function initProducts() {
    await fetch(`http://127.0.0.1:5000/listProducts`)
        .then(response => response.json())
        .then(response => {
            setProducts(response.result);
            console.log(response.result);
        )
        .catch(err => console.error(err));
}

function getProductsHtml() {
    return products.map(product =>
        <h1>{product.ProductName}</h1>
        <h1>{product.ProductDescription}</h1>
    );
}

您可以在组件初始化时调用initProducts 并在您的jsx 渲染中返回getProductsHtml

【讨论】:

  • 解决了我纠结了很久的问题,谢谢!
  • 这是我的荣幸。小心,我已经编辑了我的帖子,因为我已经覆盖了products 变量。现在它消失了。
猜你喜欢
  • 2015-12-25
  • 1970-01-01
  • 2021-03-21
  • 2021-07-19
  • 2018-03-04
  • 2019-06-03
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多