简体   繁体   English

如何从异步操作中调用 errorHandler?

[英]How does one invoke the errorHandler from async operations?

In using the errorHandler element, I am noticing that errors thrown from within Promises are not being handled.在使用errorHandler元素时,我注意到未处理从 Promises 中抛出的错误。

A sandbox reproducing the issue can be found: here .可以找到重现该问题的沙箱:此处

In short, if you throw an error directly, the errorHandler is invoked:简而言之,如果您直接抛出错误,则会调用 errorHandler:

function SyncError() {
  throw new Response('sync error', { status: 500 });
  return <p>You shouldn't see this</p>;
}

However, the error is thrown in a Promise, even if caught and rethrown, it is treated as unhandled:但是,错误是在 Promise 中抛出的,即使被捕获并重新抛出,也被视为未处理:

function AsyncError() {
  Promise.reject(new Response('sync error', { status: 500 }))
    .catch((e) => {
      throw e;
    });
  return <p>You shouldn't see this</p>;
}

These are admittedly very contrived examples, but the actual behavior I'm trying to control is how to have the errors raised from within useEffect be caught by the errorElement .诚然,这些都是非常人为的示例,但我试图控制的实际行为是如何让 useEffect 中引发的错误被useEffect errorElement In other words, something like:换句话说,类似于:

useEffect(() => {
  someMethodThatThrows()
    .then(...)
    .catch((e) => {
      // What do I do?
    });
}, []);

I have a workaround in the sandbox above that involves setting local state to the error, but that seems pretty silly.我在上面的沙箱中有一个解决方法,涉及将本地状态设置为错误,但这看起来很愚蠢。

Is this a bug or the expected behavior?这是错误还是预期的行为? If expected behavior, are there any cleaner workarounds?如果出现预期行为,是否有任何更清洁的解决方法?

UPDATE 10/10/2022 2022 年 10 月 10 日更新

After further review, it looks like this is expected behavior.经过进一步审查,这似乎预期的行为。 Found this on the react router site :反应路由器网站上找到这个:

The vast majority of your application errors are handled automatically by React Router.绝大多数应用程序错误都由 React Router 自动处理。 It will catch any errors that are thrown while:它将捕获在以下情况下抛出的任何错误:

  • rendering渲染
  • loading data加载数据中
  • updating data更新数据

In practice, this is pretty much every error in your app except those thrown in event handlers ( <button onClick> ) or useEffect .实际上,除了事件处理程序 ( <button onClick> ) 或useEffect中抛出的错误外,这几乎是应用程序中的所有错误。 React Router apps tend to have very few of either. React Router 应用程序往往都很少。

From what I understand the errorElement works with the new Data API and works in conjunction with the loader handler.据我了解, errorElement与新的数据 API 一起工作,并与loader程序处理程序一起工作。

In the case of your "async error" the error needs to be thrown when loading the route, not as an unexpected side-effect in the component after it's already been matched and rendered.在您的“异步错误”的情况下,需要在加载路由时抛出错误,而不是在已经匹配和呈现之后作为组件中的意外副作用。

Example:例子:

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<Layout />} errorElement={<ErrorBoundary />}>
      <Route path="no-error" element={<NoError />} />
      <Route path="sync-error" element={<SyncError />} />
      <Route
        path="async-error"
        element={<AsyncError />}
        loader={async (props) => {
          // handle loading requests and throwing errors here
          console.log({ props });

          throw new Response('sync error', { status: 500 });
        }}
      />
      <Route path="async-error-hack" element={<AsyncErrorHack />} />
    </Route>
  )
);

... ...

function AsyncError() {
  // Not here
  // Promise.reject(new Response('sync error', { status: 500 })).catch((e) => {
  //   throw e;
  // });
  return <p>You shouldn't see this</p>;
}

If errors are being thrown or are occurring after the component has mounted then these should be handled gracefully in the component ( ie try/catch , etc... ) or by an actual Error Boundary component.如果在组件安装抛出或发生错误,那么这些错误应该在组件中妥善处理(try/catch等... )或由实际的错误边界组件处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM