【问题标题】:useState with async function returning Promise {<pending>}useState 与异步函数返回 Promise {<pending>}
【发布时间】:2020-06-08 01:25:45
【问题描述】:

所以,我知道这个问题已经被问了 100 次了,但在我的例子中似乎没有一个解决方案有效。

我正在使用useState 挂钩将状态更新为值initialValues,该值从getInitialValues 函数返回数据

const [initialValues, setInitialValues] = useState(getInitialValues());

getInitialValues 函数进行逻辑检查并返回一个对象或另一个函数retrieveDetails()

const getInitialValues = () => {
   let details;
   if(!addressDetails) {
      details = retrieveDetails();
   } else {
      details = { 
         ...,
         ...,
         ...
      };
   }
   return details;
}

函数retrieveDetails 是一个异步函数,它进行 API 调用,我等待响应并返回从响应中接收到的对象。

const retrieveDetails = async () => {
   const addr = addressDetails[currentAddress];
   const { addressLookup } = addr;
   const key = process.env.API_KEY;
   const query = `?Key=${key}&Id=${addressLookup}`;
   const addrDetails = await new AddrService().getAddressDetails(query);
   return addrDetails;
}

但是,当我记录状态 initialValues 时,它会返回 Promise {&lt;pending&gt;}?

即使移除 API 调用并简单地返回一个对象,也会呈现相同的结果。

不确定实际返回对象的最佳解决方法?

任何帮助将不胜感激。

【问题讨论】:

标签: javascript reactjs promise async-await es6-promise


【解决方案1】:

我认为没有办法将初始数据异步获取到useState,至少现在还没有。

React 不会等待您的数据到达,当您的异步操作排队(在事件循环端)时,该函数将继续运行直到完成。

目前的惯用方式是在一个 effect 中获取数据并更新状态。

useEffect(() => {
  getData(someParam).then(data => setState(data))
}, [someParam]) 

您可以在DOCS了解更多信息

【讨论】:

  • ...然后您会收到关于尝试在未安装组件中设置状态的开发人员控制台警告。
  • @SimonB。实际上,如果您在卸载时不处理取消或忽略,大多数情况下您会得到它。我写过它,你可能会发现它很有用。 debuggr.io/react-update-unmounted-component
  • 好萨吉夫!但是使用 useReducer 加倍努力,并且在许多用例中添加单独的 useEffect 只是为了避免该警告可能会导致大量重复代码。您如何看待我下面的替代答案? :)
  • @SimonB。好吧,这超出了这个问题的范围,我确实在我的帖子中提到了类似的解决方案,尽管我更喜欢“可中止”的 useEffect
  • 谢谢!在 Promise.all 之后在 Dropzone 上工作,因为不需要按钮
【解决方案2】:
const retrieveDetails = async () => {
   const addr = addressDetails[currentAddress];
   const { addressLookup } = addr;
   const key = process.env.API_KEY;
   const query = `?Key=${key}&Id=${addressLookup}`;
   const addrDetails = await Promise.resolve(new AddrService().getAddressDetails(query))
   return addrDetails;
}


**try this once changed the function a bit**

【讨论】:

  • 现在将initialValues 状态设置为Promise {&lt;resolved&gt;: {…}}
  • 编辑检查一次,将 async 和 await 放入函数中
  • 根据定义,它不会仍然是一个承诺
  • 不幸的是,仍然收到Promise {&lt;pending&gt;}:/
  • @warmachine 仅供参考,async 和 await 只是 Promise 的糖。一旦你有了async 关键字,你的函数就会返回一个promise,你无法改变它。 await 关键字是 Promise 解析和生成器 yield 的包装器。
猜你喜欢
  • 2020-07-09
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 2019-08-02
  • 2018-04-13
  • 2019-12-23
相关资源
最近更新 更多