如何使用带有异步功能的反应钩子“useMemo”?

Posted

技术标签:

【中文标题】如何使用带有异步功能的反应钩子“useMemo”?【英文标题】:How to use the react hook "useMemo" with asynchronous functions? 【发布时间】:2021-03-24 06:37:47 【问题描述】:

我如何等待、解决/拒绝包装在反应钩子“useMemo”中的函数返回的承诺?

目前,我的代码如下所示:

  // Get the persisted email/username
  const persistedUsername = useMemo(async () => 
    let username;

    try 
      username = await AsyncStorage.getData(`@$ASYNC_STORAGE_KEY:username`);
     catch 

    return username;
  , []);  

编辑

我想要实现的是在渲染组件之前获取数据,某种“componentWillMount”生命周期。我的两个选择是:

    使用 useMemo 挂钩计算值以避免不必要的重新计算。 结合使用效果 + 使用状态。不是最好的主意,因为 useEffect 在组件绘制之后运行。

@DennisVash 在 cmets 中提出了这个问题的解决方案:

使用 useLayoutEffect 挂钩(某种 componentDidMount/componentDidUpdate)阻止所有视觉效果,其中代码在 DOM 更新后立即运行,但在浏览器有机会“绘制”这些更改之前。


如你所见,persistedUsername 仍然是一个promise(我不是在等待异步函数的结果)...

有什么想法吗?用这个钩子执行异步作业不是一个好主意吗?任何自定义钩子?

另外,以这种方式执行此操作与使用useEffect和useState相比有什么缺点?

useEffect 和 useState 也一样:

  useEffect(() => 
    // Get the persisted email/username
    (async () => 
      const persistedUsername = await AsyncStorage.getData(
        `@$ASYNC_STORAGE_KEY:username`
      );

      emailOrUsernameInput.current.setText(persistedUsername);
    )();
  , []);

谢谢。

【问题讨论】:

那么在useMemo 中声明一个promise 并调用它?... 在我看来更像是 useEffectuseState 的用例 @thedude 是的,我也这么认为,但也许可以用 useMemo 来做到这一点(我从未将它用于异步操作)。 你知道useEffectuseMemo的区别吗?它们的用途不同,为什么要在 useMemo 中执行异步操作?你基本上是在问他们之间有什么区别? @DennisVash useEffect 是在渲染之后执行动作,组件的最后一次执行,对吧?并使用Memo 执行权重动作,避免在每次渲染中重新计算它们。 【参考方案1】:

似乎问题是关于如何将componentWillMount 与钩子一起使用,这几乎等同于useLayoutEffect(因为不推荐使用componentWillMount)。

要了解更多信息,您应该解决useMemo 中的async 操作,因为您将阻塞线程(并且JS 是单线程的)。

意思是,你会等到 promise 被解决,然后它会继续计算组件。

另一方面,像 useEffect 这样的异步钩子是更好的选择,因为它不会阻塞它。

【讨论】:

以上是关于如何使用带有异步功能的反应钩子“useMemo”?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用反应钩子执行多个异步请求?

如何在反应中使用带有useState钩子的回调[重复]

如何在反应中限制经常重新渲染的组件

反应“错误:超过最大更新深度。”带有功能组件和钩子

带有异步功能的useEffect不能播放声音

如何使用钩子清理 componentDidUpdate 中的异步函数