手动刷新或写入时,React-router url 不起作用 [英] React-router urls don't work when refreshing or writing manually

查看:33
本文介绍了手动刷新或写入时,React-router url 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using React-router and it works fine while I'm clicking on link buttons, but when I refresh my webpage it does not load what I want.

例如,我在 localhost/joblist 中,一切都很好,因为我是按链接到达这里的.但是如果我刷新网页,我会得到:

For instance, I am in localhost/joblist and everything is fine because I arrived here pressing a link. But If I refresh the webpage I get:

Cannot GET /joblist

默认情况下,它不是这样工作的.最初,我的 URL 为 localhost/#/localhost/#/joblist,它们工作得非常好.但是我不喜欢这种网址,所以试图抹掉那个#,我写道:

By default, it didn't work like this. Initially I had my URL as localhost/#/ and localhost/#/joblist and they worked perfectly fine. But I don't like this kind of URL, so trying to erase that #, I wrote:

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

localhost/ 不会出现这个问题,这个问题总是返回我想要的.

This problem does not happen with localhost/, this one always returns what I want.

这个应用程序是单页的,所以/joblist不需要向任何服务器询问任何东西.

This app is single-page, so /joblist doesn't need to ask anything to any server.

我的整个路由器.

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

推荐答案

查看对已接受答案的评论以及此问题的一般性质(不起作用"),我认为这可能是一个对这里涉及的问题进行一些一般性解释的好地方.因此,此答案旨在作为 OP 特定用例的背景信息/详细说明.请耐心等待.

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

The first big thing to understand about this is that there are now 2 places where the URL is interpreted, whereas there used to be only 1 in 'the old days'. In the past, when life was simple, some user sent a request for http://example.com/about to the server, which inspected the path part of the URL, determined the user was requesting the about page, and then sent back that page.

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

With client-side routing, which is what React-Router provides, things are less simple. At first, the client does not have any JS code loaded yet. So the very first request will always be to the server. That will then return a page that contains the needed script tags to load React and React Router etc. Only when those scripts have loaded does phase 2 start. In phase 2, when the user clicks on the 'About us' navigation link, for example, the URL is changed locally only to http://example.com/about (made possible by the History API), but no request to the server is made. Instead, React Router does its thing on the client-side, determines which React view to render, and renders it. Assuming your about page does not need to make any REST calls, it's done already. You have transitioned from Home to About Us without any server request having fired.

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

So basically when you click a link, some Javascript runs that manipulates the URL in the address bar, without causing a page refresh, which in turn causes React Router to perform a page transition on the client-side.

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

But now consider what happens if you copy-paste the URL in the address bar and e-mail it to a friend. Your friend has not loaded your website yet. In other words, she is still in phase 1. No React Router is running on her machine yet. So her browser will make a server request to http://example.com/about.

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

And this is where your trouble starts. Until now, you could get away with just placing a static HTML at the webroot of your server. But that would give 404 errors for all other URLs when requested from the server. Those same URLs work fine on the client-side, because there React Router is doing the routing for you, but they fail on the server-side unless you make your server understand them.

如果您希望 http://example.com/about URL 在服务器端和客户端都工作,则需要在服务器端为其设置路由-和客户端.有道理吗?

If you want the http://example.com/about URL to work on both the server- and the client-side, you need to set up routes for it on both the server- and the client-side. Makes sense right?

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

And this is where your choices begin. Solutions range from bypassing the problem altogether, via a catch-all route that returns the bootstrap HTML, to the full-on isomorphic approach where both the server and the client run the same JS code.

.

使用 哈希历史而不是浏览器历史记录,你的关于页面的 URL 看起来像这样:http://example.com/#/about哈希 (#) 符号后面的部分不会发送到服务器.所以服务器只看到 http://example.com/ 并按预期发送索引页面.React-Router 将选取 #/about 部分并显示正确的页面.

With Hash History instead of Browser History, your URL for the about page would look something like this: http://example.com/#/about The part after the hash (#) symbol is not sent to the server. So the server only sees http://example.com/ and sends the index page as expected. React-Router will pick up the #/about part and show the correct page.

缺点:

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

.

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

With this approach, you do use Browser History but just set up a catch-all on the server that sends /* to index.html, effectively giving you much the same situation as with Hash History. You do have clean URLs however and you could improve upon this scheme later without having to invalidate all your user's favorites.

缺点:

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

.

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

In the hybrid approach, you expand upon the catch-all scenario by adding specific scripts for specific routes. You could make some simple PHP scripts to return the most important pages of your site with content included, so Googlebot can at least see what's on your page.

缺点:

  • 设置起来更加复杂
  • 对于您给予特殊待遇的那些路线,只有良好的 SEO
  • 用于在服务器和客户端上呈现内容的重复代码

.

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

What if we use Node JS as our server so we can run the same JS code on both ends? Now, we have all our routes defined in a single react-router config and we don't need to duplicate our rendering code. This is 'the holy grail' so to speak. The server sends the exact same markup as we would end up with if the page transition had happened on the client. This solution is optimal in terms of SEO.

缺点:

  • 服务器必须(能够)运行JS.我已经尝试过 Java i.c.w.Nashorn 但它对我不起作用.实际上,这主要意味着您必须使用基于 Node JS 的服务器.
  • 许多棘手的环境问题(在服务器端使用 window 等)
  • 陡峭的学习曲线
  • Server must (be able to) run JS. I've experimented with Java i.c.w. Nashorn but it's not working for me. In practice, it mostly means you must use a Node JS based server.
  • Many tricky environmental issues (using window on server-side etc)
  • Steep learning curve

.

选择一个你可以逃脱的.就我个人而言,我认为全能设置足够简单,所以这将是我的最低要求.此设置可让您随着时间的推移不断改进.如果你已经在使用 Node JS 作为你的服务器平台,我肯定会研究做一个同构应用程序.是的,一开始很难,但是一旦掌握了窍门,它实际上是解决问题的非常优雅的方法.

Choose the one that you can get away with. Personally, I think the catch-all is simple enough to set up, so that would be my minimum. This setup allows you to improve on things over time. If you are already using Node JS as your server platform, I'd definitely investigate doing an isomorphic app. Yes, it's tough at first, but once you get the hang of it it's actually a very elegant solution to the problem.

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

So basically, for me, that would be the deciding factor. If my server runs on Node JS, I'd go isomorphic; otherwise, I would go for the Catch-all solution and just expand on it (Hybrid solution) as time progresses and SEO requirements demand it.

如果您想了解有关 React 的同构(也称为通用")渲染的更多信息,有一些关于该主题的很好的教程:

If you'd like to learn more about isomorphic (also called 'universal') rendering with React, there are some good tutorials on the subject:

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

Also, to get you started, I recommend looking at some starter kits. Pick one that matches your choices for the technology stack (remember, React is just the V in MVC, you need more stuff to build a full app). Start with looking at the one published by Facebook itself:

或者从社区中选择其中之一.现在有一个不错的网站试图将它们全部编入索引:

Or pick one of the many by the community. There is a nice site now that tries to index all of them:

我从这些开始:

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

Currently, I am using a home-brew version of universal rendering that was inspired by the two starter kits above, but they are out of date now.

祝你任务顺利!

这篇关于手动刷新或写入时,React-router url 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆