【问题标题】:Async function into useEffect fetches data after componet rendering组件渲染后将异步函数转换为 useEffect 获取数据
【发布时间】:2021-03-15 20:48:05
【问题描述】:

我使用onGetAccount函数获取登录用户的地址:

const [userWalletInfo, setUserWalletInfo] = useState()

         
  async function onGetAccount() {
    const account = await client.api.asset.getAccount();
    
    return account;
    
  }  
  useEffect(() => {
    async function fetchUserWalletInfo() {
      const address = await onGetAccount();
      
      setUserWalletInfo({
        address: address,
        
      });
    }
    fetchUserWalletInfo();
  }, []);

这样我就可以访问userWalletInfo.address

问题是,如果我加载组件,然后(我的意思是当组件在本地主机上运行时,我在 VSCode 中编辑代码,我这样做是为了了解地址是否设置正确)我编辑 js。 文件添加:

<div> {userWalletInfo.address} </div>

它正确显示用户地址,但如果我刷新页面,我会得到“TypeError: Cannot read property 'address' of undefined”。
由此我推断页面是在fetchUserWalletInfo()用完之前渲染的。

【问题讨论】:

  • 您可以使用安全导航运算符:
    {userWalletInfo?.address}
    。你的问题到底是什么?
  • 它工作,你能解释一下为什么吗?我的意思是? 是干什么用的?
  • ? 是可选的链接运算符。它基本上像if 语句一样工作。即如果存在userWalletInfo 对象,则检索address 属性。我在下面的回答中也解释过。
  • 另外,? 是 ES 2020 语法,因此您需要确保使用 Bable 来填充它。如果您使用的是 create react app、NextJS 或类似的东西,您很可能不需要担心这一点,但如果您从头开始配置 React 应用程序,则需要在发布之前记住这一点
  • ?. 运算符通常被称为“可选链运算符”。它只是一种语法糖,在访问其属性之前对左侧操作数执行空值检查,因此您不会像您遇到的那样遇到运行时错误。

标签: javascript node.js reactjs asynchronous fetch


【解决方案1】:

“TypeError: 无法读取未定义的属性‘地址’”。

上面的错误信息本质上的意思是他userWalletInfo对象是undefined并且undefined上没有address属性。

userWalletInfo 未定义的原因是因为您使用异步函数获取它,这意味着当您的 render() 第一次执行时,userWalletInfo 的值仍然是 undefined

为什么在初始渲染时未定义 userWalletInfo?

因为,尽管您可能已经调用了异步函数,但异步函数不会在 Javascript 主线程上执行,而是会在包含异步函数调用的代码行中立即发送到 WEB API 环境被执行。

但是,异步函数调用之外的代码仍然是同步的,这意味着它将执行并且等待异步调用完成并返回数据。

现在,为了不再出现此错误,您需要做的就是有一个条件语句。即,在尝试检索 address 属性以显示在 DOM 上之前,您需要检查 userWalletInfo 对象是否存在。

您可以通过多种方式做到这一点:

  1. 有一个简单的 if 语句
  2. 使用可选的链接运算符?,如下所示:userWalletInfo?.address(这就像一个 if 语句。但是这是 ES 2020 语法,因此如果您想支持旧浏览器,则需要 polyfill)。
  3. 使用Short-circuiting 就像用户@Shimi 在她的回答中提到的那样。
  4. userWalletInfo 默认为空对象。 const [userWalletInfo] = useState({})。效果类似于可选链接,因为它阻止了访问undefined 运行时错误的属性。

如果您想了解有关 Javascript 事件循环和异步函数调用如何工作的更多详细信息,请从此处阅读我的回答:How Async calls, event loop and callback queue work.

【讨论】:

    【解决方案2】:

    将您的 div 更改为仅在 userWalletInfo 有地址时显示,这将避免渲染函数尝试访问未定义对象的属性。

    <div> {userWalletInfo && userWalletInfo.address} </div>
    

    更多细节:

    一开始userWalletInfo 是未定义的,因此尝试访问其地址将导致您遇到的错误。

    userWalletInfo 中有填充值之前调用渲染函数(即您的 div),因为填充发生在异步调用上,并且 React 渲染尝试渲染组件而不管可能发生的异步调用在后台。

    提供的解决方案有效,因为它在尝试显示userWalletInfo时提供了额外的谨慎,它只会在userWalletInfo未未定义时尝试访问userWalletInfo地址,从而解决之前渲染函数的失败该值已填充。

    【讨论】:

    • 它有效,你能解释一下为什么吗?或者你可以给我一些链接以便更好地理解。我是自学成才
    猜你喜欢
    • 2021-12-07
    • 1970-01-01
    • 2018-09-03
    • 2021-06-30
    • 2019-02-03
    • 2017-10-28
    • 1970-01-01
    • 2019-09-19
    • 2021-03-16
    相关资源
    最近更新 更多