javascript 将ErrorBoundary与异步生命周期函数一起使用

hm2xizp9  于 2022-12-21  发布在  Java
关注(0)|答案(3)|浏览(174)

我想构建一个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-块中结束。
我错过了什么?

juzqafwq

juzqafwq1#

async函数是返回承诺的常规函数的语法糖。async函数中的错误会导致拒绝承诺。即使拒绝的承诺未在任何地方处理并导致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>
    );
  }
hkmswyz6

hkmswyz62#

使用带有功能组件的above or below example

为我提供了一个解决方案,大概是这样的:

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>
    }
eqoofvh9

eqoofvh93#

我们来看一下Documentation
基本上它说:
错误边界是React组件,用于捕获其子组件树中任何位置的JavaScript错误,记录这些错误,并显示回退UI(而不是崩溃的组件树)。错误边界捕获呈现期间、生命周期方法中以及其下方整个树的构造函数中的错误。
所以基本上当你尝试使用ASYNC/AWAIT时,如果失败了,它会转到函数的CATCH端:

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

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

相关问题