[翻译]如何在React hooks useEffect中使用异步函数(Typescript/JS)?

5,495 阅读2分钟

乍一看,你可能会想到类似的事情,例如从远程API获取内容。

const MyFunctionnalComponent: React.FC = props => {
  useEffect(async () => {
    await loadContent();
  }, []);
  
  return <div></div>;
 }

会出现什么问题?

如果你使用Typescript, 则编译器会产生如下结果:

Argument of type '() => Promise<void>' is not assignable to parameter of type 'EffectCallback'.

让我们通过异步函数的定义来看看为什么会出现这个问题:

A function that allows to use asynchronous instructions with the await keyword which will block the statement execution as long as the Promise after which the await keyword is doesn’t resolve…

也就是说,允许将异步指令与await关键字一起使用的函数,只要不解决await关键字之后的Promise,它将阻止语句执行…

没问题吧,好吧……但是等等……

This function will also return a Promise, no matter if you explicitly return something or not. In case you return data, it will be wrapped in the resolving content of the promise that the function will create and return automatically.

无论您是否明确返回某些内容,此函数都会返回一个Promise。万一你返回数据,它将包装在promise的解决内容中,自动创建并返回。

您开始发现问题了吗?没有? 让我们阅读一下useEffect hook文档来获取更多信息。

Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function. For example, to create a subscription.

通常,effects需要在组件离开屏幕之前清除创建的资源,例如订阅或计时器ID。为此,传递给useEffect的函数应该返回一个清理函数。

使用异步函数会使回调函数返回Promise而不是cleanup函数

这就是为什么使用Typescript编译器会产生提示的原因。这种模式在JS中也不起作用,因为react不会等待Promise

如何处理useEffect中的异步函数?

通过使用以下技巧,我们可以在effects中使用异步函数:

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Create an scoped async function in the hook
    async function anyNameFunction() {
      await loadContent();
    }
    // Execute the created function directly
    anyNameFunction();
  }, []);
return <div></div>;
};

现在,你的代码是安全的,因为你什么也不返回,编译器也停止提醒。

你也可以使用IIFE

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Using an IIFE
    (async function anyNameFunction() {
      await loadContent();
    })();
  }, []);
  return <div></div>;
};

原文地址:medium.com/javascript-…