【问题标题】:Navigating to a 404 Route with Reach Router使用到达路由器导航到 404 路由
【发布时间】:2021-03-20 21:27:52
【问题描述】:

我有以下路由配置:

<Router>
 <NotFound default />
 <ResourcesContainer path="/resources" />
 <ResourceContainer path="/resources/:id" />
 ...
</Router>

这会捕获任何未处理的路由,并在未找到的 URL 处呈现 &lt;NotFound /&gt; 组件,因此如果我键入 example.com/blah,我会看到呈现的 &lt;NotFound /&gt; 组件,并且在地址栏中我看到example.com/blah。我也在页面上使用这个 URL 来显示一条消息:

找不到页面'example/blah'。

到目前为止一切顺利。但是,我还需要在 /resources/* 路由中处理 404。我的&lt;ResourcesContainer/&gt; 组件使用路径的最后一部分来访问具有该 ID 的资源的 GraphQL API。如果 API 返回告诉客户端资源不存在,我想模仿上面概述的行为。但是,我没有navigate 的页面。我可以复制&lt;NotFound /&gt; 路由并给它一个明确的path/404,然后导航到那个。但是,该 URL 将是 /404,而不是未找到的原始 resources/* 路径。

以下解决了部分问题,给了我一个页面来重定向ot,但意味着URL在所有情况下都被重写为/404

<Router>
 <ResourcesContainer path="/resources" />
 <ResourceContainer path="/resources/:id" />
 <NotFound path="/404" />
 <Redirect noThrow from="*" to="/404" />
 ...
</Router>

我该如何设置,以便我可以 navigate&lt;NotFound /&gt; 路由而不会丢失原始 URL?

【问题讨论】:

    标签: javascript reactjs routes http-status-code-404 reach-router


    【解决方案1】:

    如果找不到资源,最好将ResourceContainer 的渲染方法更改为渲染NotFound

    但是,如果您不想对 ResourceContainer 进行更改,可以使用 error boundary 将其包装起来,如下所示:

    class NotFoundErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { notFound: false };
      }
    
      static getDerivedStateFromError(error) {
        // Filter which kind of errors you want to show the error boundary for
        return { notFound: true };
      }
    
      render() {
        if (this.state.notFound) {
          // You can render any custom fallback UI
          return <NotFound />;
        }
    
        return this.props.children; 
      }
    }
    

    并像这样使用它:

    <NotFoundErrorBoundary>
     <ResourceContainer path="/resources/:id" />
    </NotFoundErrorBoundary>
    

    您的 ResourceContainer 可能会引发错误,NotFoundErrorBoundary 可以识别并表示找不到资源,它应该呈现 NotFound 页面而不是子页面。

    明确地说,我不鼓励您使用 ErrorBoundary。在我看来,这会使事情变得过于复杂。我只是向您提供信息,您如何使用它取决于您。根据用例,它在其他情况下也可能对您有用。

    【讨论】:

    • 或者如果status=4**(404——不确定这个框架是否允许ant matchers中的通配符来处理所有相关问题。)
    • 我已经为这个答案提供了赏金,因为我喜欢 ErrorBoundary 解决方案,因为它提供了一个中心位置来处理任何 404,在需要更具体的事情的情况下可以选择在本地进行更多处理呈现。但是,请注意,使用 Cypress 进行测试时会遇到问题,由于它和 React 都使用全局错误处理程序,因此无法很好地使用错误边界。
    【解决方案2】:

    错误边界不是处理它的好选择。官方网站鼓励我们使用嵌套路由哲学,例如最佳做法是在每个孩子的内部使用&lt;Router&gt;: 根:

    <Router>
     <NotFound default />
     <ResourcesContainer path="/resources/*" />
     ...
    </Router>
    

    ResourcesContainer.jsx:

    <Router>
     <NotFound default />
     <ResourcesList path="/" />
     <ResourceDetail path="/:id" />
     ...
    </Router>
    

    如果我们在 API 调用中得到 404,如何渲染 &lt;NotFound /&gt; 很简单:

    if (API.error) return <NotFound />;
    if (API.data) return ...;
    

    如何简化? 我们可以有一个这样的包装器: 未找到路由器

    <Router>
     <NotFound default />
     {children}
    </Router>
    

    【讨论】:

    • 您还没有解决问题提出的问题。 &lt;NotFound/&gt; 组件永远不会被渲染,因为所有路径都将被 /:id 捕获。
    • 如果他只是限制一个错误,我会说这是最好的选择。每个用例都应该有自己的解决方案。否则我们现在都会使用 wix.. XD
    • @NathanToulbert 我同意每个用例都应该有自己的解决方案,但在这种情况下,这不是我在问题中概述的用例的解决方案。
    • @NathanToulbert 我添加了How to render &lt;NotFound /&gt; if we get 404 in API call?
    【解决方案3】:

    在我看来,这不是路线问题。渲染/resources/:id的组件基本有loadingfoundData404三种状态。如果您只是为每个状态渲染不同的组件,那么您可以只渲染相同的 404 组件。很简单,如果您不想更改网址,请不要导航。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 2019-05-17
      • 2017-04-28
      • 2021-03-29
      • 2021-02-13
      • 1970-01-01
      相关资源
      最近更新 更多