小编典典

手动刷新或写入时,React-router url 不起作用

all

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

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

Cannot GET /joblist

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

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

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

编辑: 这个应用程序是单页的,所以/joblist不需要向任何服务器询问任何内容。

EDIT2: 我的整个路由器。

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);
});

阅读 196

收藏
2022-02-28

共1个答案

小编典典

查看对已接受答案的评论和这个问题的一般性质(“不工作”),我认为这可能是对这里涉及的问题进行一些一般性解释的好地方。因此,此答案旨在作为 OP
特定用例的背景信息/详细说明。请多多包涵。

服务器端与客户端

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

使用 React-Router 提供的客户端路由,事情就不那么简单了。起初,客户端还没有加载任何 JS
代码。所以第一个请求将永远是服务器。然后将返回一个页面,其中包含加载 React 和 React Router 等所需的脚本标签。只有当这些脚本加载后,阶段
2 才会开始。例如,在第 2 阶段,当用户单击“关于我们”导航链接时,URL 仅在本地
更改为http://example.com/about(由History API实现),但 不会向服务器发出请求. 相反,React Router
在客户端做它的事情,决定渲染哪个 React 视图,然后渲染它。假设您的关于页面不需要进行任何 REST
调用,它已经完成了。您已从主页转换到关于我们,而没有触发任何服务器请求。

所以基本上当你点击一个链接时,一些 Javascript 会运行来操纵地址栏中的 URL, 而不会导致页面刷新 ,这反过来会导致 React
Router 在客户端 执行页面转换。

但是现在考虑如果您将 URL 复制粘贴到地址栏中并将其通过电子邮件发送给朋友会发生什么。您的朋友尚未加载您的网站。也就是说,她还处于 第一阶段
。她的机器上还没有运行 React Router。所以她的浏览器会 http://example.com/about.

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

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

如果您希望http://example.com/aboutURL 同时在服务器端和客户端工作,您需要在服务器端和客户端为其设置路由。有道理吗?

这就是您的选择开始的地方。解决方案的范围从完全绕过问题,通过返回引导 HTML 的包罗万象的路线,到服务器和客户端都运行相同 JS 代码的全面同构方法。

完全绕过问题:哈希历史

使用Hash History而不是Browser
History
,关于页面的 URL 将如下所示:
http://example.com/#/about 哈希 ( #)
符号后面的部分不会发送到服务器。所以服务器只能http://example.com/按预期看到并发送索引页。React-Router
将拾取该#/about部分并显示正确的页面。

缺点

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

包罗万象

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

缺点

  • 设置更复杂
  • 仍然没有好的SEO

杂交种

在混合方法中,您通过为特定路线添加特定脚本来扩展包罗万象的方案。您可以制作一些简单的 PHP 脚本来返回包含内容的网站最重要的页面,这样 Googlebot
至少可以看到您页面上的内容。

缺点

  • 设置更复杂
  • 只有那些你给予特殊待遇的路线才有好的 SEO
  • 复制用于在服务器和客户端上呈现内容的代码

同构

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

缺点

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

我应该使用哪个?

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

所以基本上,对我来说,这将是决定因素。如果我的服务器在 Node JS 上运行,我会采用同构的;否则,我会选择 Catch-all
解决方案,并随着时间的推移和 SEO 需求的需要对其进行扩展(混合解决方案)。

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

另外,为了让您入门,我建议您查看一些入门工具包。选择一个与你的技术栈选择相匹配的技术栈(记住,React 只是 MVC 中的
V,你需要更多的东西来构建一个完整的应用程序)。首先查看 Facebook 自己发布的内容:

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

我从这些开始:

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

祝你的任务好运!

2022-02-28