使用 Reach Router 导航到 404 路由
Navigating to a 404 Route with Reach Router
我有以下路由配置:
<Router>
<NotFound default />
<ResourcesContainer path="/resources" />
<ResourceContainer path="/resources/:id" />
...
</Router>
这会捕获任何未处理的路由,并在未找到的 URL 处呈现 <NotFound />
组件,因此如果我键入 example.com/blah
,我会看到 <NotFound />
组件呈现,在地址栏中我看到 example.com/blah
。我也在页面上用这个URL来显示一条信息:
The page 'example/blah' was not found.
到目前为止一切顺利。但是,我还需要在 /resources/*
路由中处理 404。我的 <ResourcesContainer/>
组件使用路径的最后一部分为具有该 ID 的资源命中 GraphQL API。如果 API returns 告诉客户端资源不存在,我想模仿上面概述的行为。但是,我没有要 navigate 的页面。我可以复制 <NotFound />
路由并给它一个 /404
的显式 path
,然后导航到那个。然而 URL 将是 /404
而不是未找到的原始 resources/*
路径。
以下解决了部分问题,给我一个重定向 ot 的页面,但意味着 URL 在所有情况下都被重写为 /404
:
<Router>
<ResourcesContainer path="/resources" />
<ResourceContainer path="/resources/:id" />
<NotFound path="/404" />
<Redirect noThrow from="*" to="/404" />
...
</Router>
我该如何设置才能navigate
到<NotFound />
路线而不丢失原来的URL?
我认为这不是路由问题。渲染 /resources/:id
的组件基本上有三种状态:loading
、foundData
和 404
。如果您只是为每个状态渲染不同的组件,那么您可以只渲染相同的 404
组件。很简单,如果您不想更改 url,请不要导航。
如果找不到资源,最好的选择是将 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。在我看来,这会使事情过于复杂。我只是给你提供信息,你如何使用它取决于你。根据用例,它在其他上下文中也可能对您有用。
错误边界不是处理它的好选择。官方网站鼓励我们使用嵌套路线理念,例如最佳做法是在每个 child 中使用 <Router>
:
根:
<Router>
<NotFound default />
<ResourcesContainer path="/resources/*" />
...
</Router>
ResourcesContainer.jsx:
<Router>
<NotFound default />
<ResourcesList path="/" />
<ResourceDetail path="/:id" />
...
</Router>
如果我们在 API 调用中得到 404,如何渲染 <NotFound />
?
很简单:
if (API.error) return <NotFound />;
if (API.data) return ...;
如何简化呢?
我们可以像这样有一个包装器:
没有找到路由器
<Router>
<NotFound default />
{children}
</Router>
我有以下路由配置:
<Router>
<NotFound default />
<ResourcesContainer path="/resources" />
<ResourceContainer path="/resources/:id" />
...
</Router>
这会捕获任何未处理的路由,并在未找到的 URL 处呈现 <NotFound />
组件,因此如果我键入 example.com/blah
,我会看到 <NotFound />
组件呈现,在地址栏中我看到 example.com/blah
。我也在页面上用这个URL来显示一条信息:
The page 'example/blah' was not found.
到目前为止一切顺利。但是,我还需要在 /resources/*
路由中处理 404。我的 <ResourcesContainer/>
组件使用路径的最后一部分为具有该 ID 的资源命中 GraphQL API。如果 API returns 告诉客户端资源不存在,我想模仿上面概述的行为。但是,我没有要 navigate 的页面。我可以复制 <NotFound />
路由并给它一个 /404
的显式 path
,然后导航到那个。然而 URL 将是 /404
而不是未找到的原始 resources/*
路径。
以下解决了部分问题,给我一个重定向 ot 的页面,但意味着 URL 在所有情况下都被重写为 /404
:
<Router>
<ResourcesContainer path="/resources" />
<ResourceContainer path="/resources/:id" />
<NotFound path="/404" />
<Redirect noThrow from="*" to="/404" />
...
</Router>
我该如何设置才能navigate
到<NotFound />
路线而不丢失原来的URL?
我认为这不是路由问题。渲染 /resources/:id
的组件基本上有三种状态:loading
、foundData
和 404
。如果您只是为每个状态渲染不同的组件,那么您可以只渲染相同的 404
组件。很简单,如果您不想更改 url,请不要导航。
如果找不到资源,最好的选择是将 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。在我看来,这会使事情过于复杂。我只是给你提供信息,你如何使用它取决于你。根据用例,它在其他上下文中也可能对您有用。
错误边界不是处理它的好选择。官方网站鼓励我们使用嵌套路线理念,例如最佳做法是在每个 child 中使用 <Router>
:
根:
<Router>
<NotFound default />
<ResourcesContainer path="/resources/*" />
...
</Router>
ResourcesContainer.jsx:
<Router>
<NotFound default />
<ResourcesList path="/" />
<ResourceDetail path="/:id" />
...
</Router>
如果我们在 API 调用中得到 404,如何渲染 <NotFound />
?
很简单:
if (API.error) return <NotFound />;
if (API.data) return ...;
如何简化呢? 我们可以像这样有一个包装器: 没有找到路由器
<Router>
<NotFound default />
{children}
</Router>