React 路由器 URL 在手动刷新或写入时不起作用

2022-08-29 22:07:24

我正在使用React-router,当我点击链接按钮时它工作正常,但是当我刷新我的网页时,它不会加载我想要的东西。

例如,我进去了,一切都很好,因为我按链接到达这里。但是,如果我刷新网页,我会得到:localhost/joblist

Cannot GET /joblist

默认情况下,它不像这样工作。最初我有我的URL作为和他们工作得很好。但是我不喜欢这种URL,所以试图删除它,我写道:localhost/#/localhost/#/joblist#

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

这个问题不会发生在 ,这个总是返回我想要的。localhost/

此应用程序是单页的,因此不需要向任何服务器询问任何内容。/joblist

我的整个路由器。

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

答案 1

服务器端与客户端

首先要了解的是,现在有2个地方可以解释URL,而在“过去”只有1个地方。过去,当生活很简单时,一些用户向服务器发送请求,服务器检查URL的路径部分,确定用户正在请求关于页面,然后发回该页面。http://example.com/about

使用客户端路由,这是React Router提供的,事情就不那么简单了。起初,客户端尚未加载任何 JavaScript 代码。因此,第一个请求将始终发送到服务器。然后,这将返回一个页面,其中包含加载 React 和 React Router 等所需的脚本标记。仅当加载了这些脚本后,阶段 2 才会启动。例如,在第 2 阶段,当用户单击“关于我们”导航链接时,URL 仅在本地更改为(由历史记录 API 实现),但不向服务器发出请求。相反,React Router 在客户端执行其操作,确定要呈现的 React 视图,并对其进行呈现。假设您的关于页面不需要进行任何REST调用,它已经完成了。您已从“主页”转换为“关于我们”,但未触发任何服务器请求。http://example.com/about

因此,基本上,当您单击链接时,一些JavaScript会运行操作地址栏中的URL,而不会导致页面刷新,这反过来又会导致React Router在客户端执行页面转换。

但现在考虑一下,如果将URL复制粘贴到地址栏中并通过电子邮件发送给朋友,会发生什么情况。您的朋友尚未加载您的网站。换句话说,她仍处于第1阶段。没有 React Router 正在她的机器上运行。因此,她的浏览器将向 .http://example.com/about

这就是你的麻烦开始的地方。到目前为止,您只需在服务器的webroot上放置一个静态HTML即可。但是,当从服务器请求时,这将为所有其他URL提供404错误。这些相同的URL在客户端工作正常,因为React Router正在为你做路由,但是除非你让你的服务器理解它们,否则它们在服务器端会失败。

组合服务器端和客户端路由

如果希望 URL 在服务器端和客户端都有效,则需要在服务器端和客户端为其设置路由。这是有道理的,对吧?http://example.com/about

这就是您的选择开始的地方。解决方案的范围从完全绕过问题,通过返回引导HTML的捕获所有路由,到服务器和客户端运行相同JavaScript代码的全功能同构方法。

完全绕过问题:哈希历史记录

使用哈希历史记录,而不是浏览器历史记录,您的关于页面的URL将如下所示:http://example.com/#/about

哈希 () 符号后面的部分不会发送到服务器。因此,服务器仅按预期查看并发送索引页。React Router将拾取该部分并显示正确的页面。#http://example.com/#/about

缺点

  • “丑陋”的网址
  • 使用此方法无法进行服务器端呈现。就搜索引擎优化(SEO)而言,您的网站由一个页面组成,几乎没有任何内容。

包罗万象

使用这种方法,您确实使用浏览器历史记录,但只需在发送到 的服务器上设置一个包罗万象,有效地为您提供与哈希历史记录大致相同的情况。但是,您确实有干净的URL,以后可以改进此方案,而不必使所有用户的收藏夹无效。/*index.html

缺点

  • 设置更复杂
  • 仍然没有好的搜索引擎优化

混合

在混合方法中,您可以通过为特定路由添加特定脚本来扩展捕获所有方案。您可以制作一些简单的PHP脚本来返回您网站上最重要的页面,其中包含内容,因此Googlebot至少可以看到您页面上的内容。

缺点

  • 设置更加复杂
  • 只有良好的SEO才能为您提供特殊待遇的那些路线
  • 复制代码以在服务器和客户端上呈现内容

同构

如果我们使用Node.js作为我们的服务器,这样我们就可以在两端运行相同的JavaScript代码,那会怎么样?现在,我们在单个 react-router 配置中定义了所有路由,并且不需要复制我们的渲染代码。可以说,这就是“圣杯”。服务器发送的标记与我们最终在客户端上发生页面转换时的标记完全相同。该解决方案在SEO方面是最佳的。

缺点

  • 服务器必须(能够)运行 JavaScript。我已经将Java与Nashorn一起进行了实验,但它对我不起作用。在实践中,这主要意味着您必须使用基于Node.js服务器。
  • 许多棘手的环境问题(在服务器端使用等)window
  • 陡峭的学习曲线

我应该使用哪个?

选择一个你可以逃脱的。就个人而言,我认为包罗万象的设置非常简单,因此这将是我的最小值。此设置允许您随着时间的推移改进。如果您已经在使用Node.js作为您的服务器平台,我肯定会研究做一个同构应用程序。是的,一开始很难,但是一旦你掌握了它的窍门,它实际上是一个非常优雅的问题解决方案。

所以基本上,对我来说,这将是决定性因素。如果我的服务器在Node上运行.js,我会去同构;否则,我会选择Catch-all解决方案,并随着时间的流逝和SEO要求而扩展它(混合解决方案)。

如果你想了解更多关于使用 React 进行同构(也称为“通用”)渲染的信息,这里有一些关于这个主题的好教程:

另外,为了帮助您入门,我建议您查看一些入门套件。选择一个与你选择的技术堆栈相匹配的(请记住,React只是MVC中的V,你需要更多的东西来构建一个完整的应用程序)。首先看看Facebook自己发布的那篇文章:

或者从社区的众多选择之一。现在有一个不错的网站试图索引所有这些网站:

我从这些开始:

目前,我正在使用通用渲染的自制版本,该版本受到上述两个初学者工具包的启发,但它们现在已经过时了。

祝你任务顺利!


答案 2

如果您使用Apache作为Web服务器,则可以将其插入到文件中:.htaccess

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]
</IfModule>

我正在使用,这种方法是包罗万象的,可能是让你入门的最简单方法。react: "^16.12.0"react-router: "^5.1.2"