当 URL 不匹配任何路由并且 URL 包含 /#/ 时如何使用 ReactJS 显示 404

Posted

技术标签:

【中文标题】当 URL 不匹配任何路由并且 URL 包含 /#/ 时如何使用 ReactJS 显示 404【英文标题】:How to display 404 when URL doesn't match any route and when the URL contains /#/ using ReactJS 【发布时间】:2018-06-28 22:48:41 【问题描述】:

这是我第一次使用 ReactJS 并且不是我的项目,但是我正在尝试将任何不存在的路由重定向到我制作的 404 页面。当 URL 包含 /#/ 时输入任何与路由不匹配的 URL 除了,我的 404 页面当前正在按预期显示。

比如这个网址会重定向到我的404页面:

http://localhost:8080/non-existent-url

但是这个 URL 只会加载我应用的默认路由(主页):

http://localhost:8080/#/non-existent-url

我不知道/#/ 是做什么用的,看来该应用程序将显示带有或不带它的有效路线的页面。

精简路线文件:

import React from "react";
import  Router, Route, IndexRoute, browserHistory, hashHistory, Redirect  from "react-router/es";
import willTransitionTo from "./routerTransition";
import App from "./App";
import DashboardContainer from "./components/Dashboard/DashboardContainer";
import DashboardAccountsOnly from "./components/Dashboard/DashboardAccountsOnly";
import NotFound from './components/NotFound';

const history = __HASH_HISTORY__ ? hashHistory : browserHistory;

class Auth extends React.Component 
    render() return null; 


const routes = (
    <Route path="/" component=App onEnter=willTransitionTo>
        <IndexRoute component=DashboardContainer/>
        <Route path="/auth/:data" component=Auth/>
        <Route path="/dashboard" component=DashboardContainer/>

        <Route path='*' exact=true component=NotFound />
    </Route>
);

export default class Routes extends React.Component 
    render() 
        return <Router history=history routes=routes />;
    

404(未找到)组件:

import React from 'react';
import Link from "react-router/es";
import Translate from "react-translate-component";

var image = require("assets/404.png");

const NotFound = () =>

    <div className="grid-block main-content wrap regular-padding">
        <div className="grid-content small-12" style=marginTop:"200px">
            <div style= textAlign:"center">
                <img style=marginBottom:"1.2rem" src=image />
                <h3>404 page not found</h3>
                <p>This page does not exist.</p>
                <Link className="button" to="/dashboard">
                    <Translate style=color:"#fff" content="account.home" />
                </Link>
            </div>
        </div>
    </div>

export default NotFound;

当 URL 不匹配任何路由并且当 URL 包含 /#/ 时,我如何将用户重定向到我的 404 页面?

【问题讨论】:

你使用的是哪个版本的 React Router? 您可能想阅读 React Router 文档中的 之间的区别。 reacttraining.com/react-router/web/api/HashRouter 看起来你需要做的就是使用browserHistory而不是hashHistoryconst history = browserHistory; @MattD 我正在使用 react-router v3.0.2。我尝试了 Shubham 的建议,但没有任何区别。 Please check here。它会帮助你。 【参考方案1】:

对于 react-router

如果你想显示错误页面而不改变路径

<Route path='*' exact=true component=errorcomponent />

如果要显示错误页面并更改路径

<Route path='/error' component=errorcomponent />
 // use redirect to  change the Url
<Redirect from='*' to='/error' />

对于反应路由器 4

保持路径

<Switch>
    <Route exact path="/" component=component />
    <Route component=errorcomponent />
 </Switch>

更改网址。

 <Switch>
    <Route path="/comp" component=component />
   <Redirect to="/error" />
 </Switch>

无论您在交换机中放置路由标签的任何位置,都必须放置重定向标签。

【讨论】:

这究竟如何解决处理带有 /#/ 的路由的问题?请详细说明这一点。另外,我认为您没有为 v4 示例正确设置重定向,或者您提供的示例不完整。【参考方案2】:

根据我在您的代码中看到的内容,尝试在哈希历史记录和浏览器历史记录之间切换是行不通的。当您在任何会中断的地方点击“/#”时,总是会点击您的通用“/”路线。

哈希 URL 是一种处理不再是问题的旧方法。有关更多详细信息,请参阅此 SO 问题及其接受的答案。

Doing links like Twitter, Hash-Bang #! URL's

所以是的,除非你有一些疯狂的理由仍然支持 URL 中的哈希,否则删除哈希历史并简单地使用浏览器历史。然后,您在提供的代码示例中定义的路线应该可以工作。

【讨论】:

这个答案是否仍然适用,即使它在技术上不是一个哈希爆炸(没有'!')?我从路由文件中删除了对 hashHistory 的所有引用,但不存在的 URL 仍然路由到应用主页,而不是 404。 @dom_ahdigital 我会说您设置路由的方式在某些方面不正确,或者它是另一个导致您的全部路径不被命中的项目。查看您的 React Router 版本的所有文档,以确保您设置正确(这可能会有所帮助:github.com/ReactTraining/react-router/blob/v3/docs/guides/…)。除此之外,如果实际上没有什么需要您坚持使用 3.0.2,我会考虑简单地升级到最新版本。 @dom_ahdigital 另外,澄清一下,您还没有尝试使用/#/non-existant-url 是吗?【参考方案3】:

您可以访问location.hash 值并将其设置为空白。

但正如已经很好地描述的那样,这是多年来的标准 http,除非有充分的理由,否则您不应该关心。

你可以看到它像http://localhost:8080/?non-existent-url 这意味着去/ 带有路径参数non-existent-url 你也想重定向吗?

【讨论】:

【参考方案4】:

在创建 URL 时应该避免一些不安全的字符,其中之一是#

字符“#”是不安全的,应始终进行编码,因为它是 在万维网和其他系统中用于将 URL 与 可能跟随它的片段/锚标识符。

服务器在解析路由时将传递# 之前的字符串以获取请求的页面,然后如果使用# 之后的字符串指定任何内容,它将移动页面的确切片段,直到出现任何不安全字符。

所以,在# 之前的字符串中为空,这就是它重定向到/ 的原因,这是一个有效的路由,它重定向到component App。而且由于没有定义片段,所以什么也没发生。

为了使这个工作我们需要告诉nginx or any other server在发送请求前删除所有#

在这种情况下,

http://localhost:8080/#/non-existent-url

将转换为,

http://localhost:8080/non-existent-url

这将解决问题。 看这个链接看How to rewrite rule in nginx

【讨论】:

鉴于我无法安全更新的旧版本 react 路由器的情况,我将不得不使用 URL 重写。【参考方案5】:

你可以用这个

<Route exact insecure component=NotFound />

【讨论】:

您能否提供更多解释,说明为什么这是解决问题的解决方案? 这不起作用,产生完全相同的结果。【参考方案6】:

问题在于,在 URL http://localhost:8080/#/non-existent-url 中,路由只是 /,这就是它访问您的应用程序组件的原因。标准 URL 中 # 的意图意味着转到页面中的某个位置。因此,您的 url 是说“加载页面后转到 / 页面并转到此特定位置”。

从路由的角度来看,/你的路由,所以它找到了。老实说,如果您没有使用 5 年前的 hash-bang 风格的路由,那么这就是预期的行为。在那种情况下(如果你被那些为这类页面或其他东西添加书签的人所困扰)强制这样的东西“找不到”,我会重新编写 URL。

SPA 应用程序已经在服务器上重写了传入的 URL,因此它们都指向一个页面。添加一个规则,作为重写的一部分,它会删除 #(如果您不在应用中使用它)。

因此,http://localhost:8080/#/non-existent-url 将在应用程序内部作为http://localhost:8080/non-existent-url 处理。

【讨论】:

【参考方案7】:

您应该将Router 组件作为Routes 的父组件并添加此路由

<Route path='*' component=() => NotFound />

const routes = (
    <Router>
        <div>
            <Route path="/" component=App onEnter=willTransitionTo
            <IndexRoute component=DashboardContainer/>
            <Route path="/auth/:data" component=Auth/>
            <Route path="/dashboard" component=DashboardContainer/>

            <Route path='*' component=() => NotFound />
        </div>
    </Router>
);

【讨论】:

以上是关于当 URL 不匹配任何路由并且 URL 包含 /#/ 时如何使用 ReactJS 显示 404的主要内容,如果未能解决你的问题,请参考以下文章

当 url 匹配相同的路由时,vue3 router.push 不更新组件?

Flask 在 URL 中添加斜杠,没有路由匹配

Laravel 前缀路由和 json 文件 url 不匹配

当 url 匹配相同的路由时,React 路由器不会重新加载页面

当 ReactJS 中的 URL 不匹配时如何返回 404 状态码

错误:无法匹配任何路由。 URL 段:“配置文件”或加载资源失败:服务器响应状态为 401(未授权)