【问题标题】:Use ErrorBoundary together with asynchronous lifecycle-functions将 ErrorBoundary 与异步生命周期函数一起使用
【发布时间】:2018-10-05 23:12:22
【问题描述】:

我想构建一个 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-block 时,它永远不会被调用/触发。

我在这里错过了什么?

【问题讨论】:

    标签: javascript reactjs typescript asynchronous


    【解决方案1】:

    让我们看看Documentation

    基本上是这样说的:

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

    所以基本上当您尝试使用 ASYNC/AWAIT 并且它失败时,它会在您的函数的 CATCH 端消失:

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

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

    【讨论】:

    • 删除了try/catch,但componentDidCatch 仍然没有被击中。只有在开发工具中,我才能从承诺被拒绝的部分看到 Uncaught (in promise) Error: Internal Server Error reject(new Error(xhr.statusText))
    • @KingKerosin 你能把代码放在componentDidCatch里面吗?
    • 哪个代码?应该发生什么? componentDidCatch 永远不会被击中
    【解决方案2】:

    async 函数是返回承诺的常规函数​​的语法糖。 async 函数中的错误会导致 promise 被拒绝。即使拒绝的 Promise 没有在任何地方处理并导致 Uncaught (in promise) 错误,它也不会被错误边界捕获。

    正如the reference 所说,

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

    解决方案是在出错时更改组件状态并在下一次渲染时处理它。 render是可以同步重新抛出错误的地方。

    example:

      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>
        );
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 2019-08-20
      相关资源
      最近更新 更多