使用ErrorBoundary和异步生命周期函数一起

10

我想要构建一个React组件,在 componentDidMount 生命周期异步加载数据。

以下是当前函数的代码(使用 TypeScript 编写):

async componentDidMount(): Promise<void> {
    try {
        const { props: { teamId }, state: { } } = this;
        const awaitableData = await UrlHelper.getDataAsync("some-fancy-url");

        // ... do something with awaitableData
    } catch(e) {
        console.log("Some error occured");
        throw e;
    }
}
render函数返回用ErrorBoundary组件包装的标记,该组件已经实现了componentDidCatch。但是,在等待的调用被拒绝时,这个函数从未被调用或触发,最终进入了catch块中。我错过了什么?
3个回答

21

async函数是一种返回promise的普通函数的语法糖。在async函数中出现错误会导致promise被拒绝。即使被拒绝的promise没有被任何地方处理,最终会导致Uncaught (in promise)错误,也不会被错误边界捕获。

正如文档所述:

错误边界不会捕获以下错误:<...> 异步代码(例如setTimeout或requestAnimationFrame回调)

解决方法是在出现错误时更改组件状态,并在下次渲染时进行处理。在render中可以同步重新抛出错误。

这里有一个例子

  state = { error: null };

  async componentDidMount() {
    try {
      await new Promise(resolve => setTimeout(resolve, 2000));
      throw new Error('Foo error');
    } catch (error) {
      this.setState({ error });
    }
  }

  render() {
    if (this.state.error) {
      throw this.state.error;
    }

    return (
      <p>Foo</p>
    );
  }

0

在函数组件中使用上面或下面的示例

为我提供了一个解决方案,类似于这样:

    const SomComponent: JSX.Element = () => {
    const [state, setState] = useState({error: null, info: null})

    ... // something here setState the error

        if (state.error) {
          throw new Error('example') // Example throws to the error boundary
        }
        return <div> Some Component </div>
    }

-4

让我们来看一下文档

基本上它说:

错误边界是React组件,可以捕获其子组件树中任何位置的JavaScript错误,记录这些错误,并显示替代UI而不是崩溃的组件树。错误边界在渲染期间、生命周期方法和它们下面整个树的构造函数中捕获错误。

所以基本上当您尝试使用ASYNC/AWAIT并且失败时,它将转到函数的CATCH部分:

catch(e) {
    console.log("Some error occured");
    throw e;
}

而且错误不会被componentDidMount抛出。 实际上,如果删除try catch方法,componentDidMount将处理错误。


已删除 try/catch 但仍然无法触发 componentDidCatch。只有在开发工具中,我才能看到来自拒绝承诺的部分 reject(new Error(xhr.statusText))Uncaught (in promise) Error: Internal Server Error - KingKerosin
@KingKerosin,你能把代码放在componentDidCatch里面吗? - Prince Hernandez
哪段代码?应该发生什么?componentDidCatch 从未被触发。 - KingKerosin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接