【问题标题】:React-router stops working when error boundary catches an error in route当错误边界捕获路由错误时,React-router 停止工作
【发布时间】:2022-04-17 20:08:02
【问题描述】:

下面链接的 codepen 使用 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"));

【问题讨论】:

    标签: reactjs react-router react-error-boundary


    【解决方案1】:

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

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

      componentDidUpdate(prevProps) {
        if (prevProps.location.pathname !== this.props.location.pathname) {
          this.setState({ hasError: false });
        }
      }
    

    由于您使用的是 render 属性,因此您必须手动将 route props 传递给 ErrorBoundary 组件:

    例如:

    <Route
      exact
      path="/"
      render={props => (
        <ErrorBoundary {...props}>
          <HomeScreen {...props} />
        </ErrorBoundary>
      )}
    />
    

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

    【讨论】:

      【解决方案2】:

      作为记录,我认为如果您不希望在更改路由后仍然存在错误状态问题并在 r.r v6 中为每个路由定义错误边界,您可以如下解决:

      a:定义变量以保存上一个位置:

        constructor(props) {
              super(props);
              this.state = { error: null, errorInfo: null };
              this.prevPath = null;
        }
      
        static getDerivedStateFromError(error) {
          return { error: true, errorInfo: error };
        }
      

      b:在组件上设置当前位置确实挂载

        componentDidMount() {
          this.prevPath = window.location.pathname;
        }
      

      c: 最后确实更新应该是这样的:

        componentDidUpdate() {
          if (window.location.pathname !== this.prevPath)
            this.setState({ error: null, errorInfo: null });
          this.prevPath = window.location.pathname;
        }
      

      d: 像这样包装出口:

        <ErrorBoundry>
          <Outlet />
        </ErrorBoundry>
      

      【讨论】:

        猜你喜欢
        • 2017-10-07
        • 2019-04-01
        • 1970-01-01
        • 2019-11-26
        • 2020-02-19
        • 1970-01-01
        • 2017-02-03
        • 2018-08-14
        • 2013-01-01
        相关资源
        最近更新 更多