当错误边界捕获路由中的错误时,React-router 停止工作

Svi*_*ish 4 reactjs react-router react-error-boundary

下面链接的代码笔使用react-router错误边界来捕获每个路由中的错误。

如果您单击“商店”,则会按预期捕获错误,其他链接将不再起作用。这里发生了什么?为什么react-router-dom看起来停止工作?执行此操作的“正确”方法是什么?是<ErrorBoundary>组件的问题,还是路由组件的包装方式的问题?

https://codepen.io/mpontus/pen/NyKNoL


如果 codepen 链接出现问题:

const { BrowserRouter, Switch, Route, NavLink } = ReactRouterDOM;

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  componentDidCatch(error, info) {
    this.setState({ hasError: true });
  }

  render() {
    if (this.state.hasError) {
      return <h1>An error has occured.</h1>;
    }

    return this.props.children;
  }
}

const HomeScreen = () => <h3>Home</h3>;

const ProfileScreen = () => <h3>Profile Screen</h3>;

const ShopScreen = () => {
  throw new Error("Error during render");
};

const App = () => (
  <BrowserRouter>
    <div className="container">
      <nav className="nav nav-pills">
        <NavLink exact className="nav-link" activeClassName="active" to="/">
          Home
        </NavLink>
        <NavLink className="nav-link" activeClassName="active" to="/profile">
          Profile
        </NavLink>
        <NavLink className="nav-link" activeClassName="active" to="/shop">
          Shop
        </NavLink>
      </nav>
      <Switch>
        <Route
          exact
          path="/"
          render={() => (
            <ErrorBoundary>
              <HomeScreen />
            </ErrorBoundary>
          )}
        />
        <Route
          path="/profile"
          render={() => (
            <ErrorBoundary>
              <ProfileScreen />
            </ErrorBoundary>
          )}
        />
        <Route
          path="/shop"
          render={() => (
            <ErrorBoundary>
              <ShopScreen />
            </ErrorBoundary>
          )}
        />
      </Switch>
    </div>
  </BrowserRouter>
);

ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)

Mat*_*tta 7

简而言之,由于您ErrorBoundary对每个路线都重复使用,因此它永远不会被卸载(这是设计使然)。因此,它的hasError状态在每条路线上都持续存在。

您可以通过在组件内的位置发生变化时更新状态来缓解这种情况ErrorBoundary

  componentDidUpdate(prevProps) {
    if (prevProps.location.pathname !== this.props.location.pathname) {
      this.setState({ hasError: false });
    }
  }
Run Code Online (Sandbox Code Playgroud)

由于您使用的是renderprop,因此您必须手动将路由 prop传递给ErrorBoundary组件:

例如:

<Route
  exact
  path="/"
  render={props => (
    <ErrorBoundary {...props}>
      <HomeScreen {...props} />
    </ErrorBoundary>
  )}
/>
Run Code Online (Sandbox Code Playgroud)

工作演示(由于此codesandbox位于 中development,它将显示错误覆盖,因此您必须关闭错误窗口才能继续):

编辑误差边界