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

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

问题描述

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

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

例如,我进入localhost / joblist,一切都很好,因为我来到这里按一个链接。但是,如果我刷新我得到的网页:无法获取/工作列表

For instance, I am into 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: 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 don't need to ask anything to any server.

EDIT2 :我的整个路由器。

My entire router.

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阶段,当用户点击关于我们导航链接时,该网址仅在本地更改为 http://example.com/about (由历史记录API 提供) ,但没有向服务器发出请求。相反,React Router在客户端执行它的操作,确定要呈现和呈现的React视图。假设您的about页面不需要进行任何REST调用,那么它已经完成了。您已经从Home转换为About Us而没有任何服务器请求被解雇。

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 it's 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复制粘贴到地址栏并通过电子邮件发送给朋友,会发生什么。您的朋友尚未加载您的网站。换句话说,她仍处于阶段1 。没有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.

哈希历史而不是< a href =https://github.com/jintoppy/react-training/blob/master/basic/node_modules/react-router/docs/guides/Histories.md#browserhistory\"rel =noreferrer>浏览器历史记录,about页面的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 的服务器上,有效地为您提供与哈希历史记录相同的情况。但是,您确实拥有干净的网址,您可以稍后改进此计划,而不必使用户的所有收藏失效。

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.

下行


  • 设置起来更复杂

  • 这些路线只有优秀的搜索引擎优化你给予特殊待遇

  • 复制用于在服务器和客户端上呈现内容的代码

如果我们使用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的服务器。

  • 许多棘手的环境问题(在服务器端使用窗口等) )

  • 陡峭的学习曲线

  • 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 that 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上运行,我会同构,否则我会选择Catch-all解决方案并随着时间的推移扩展它(混合解决方案)并且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 on isomorphic (also called 'universal') rendering with React, there are some good tutorials on the subject:

  • React to the future with isomorphic apps
  • The Pain and the Joy of creating isomorphic apps in ReactJS
  • How to Implement Node + React Isomorphic JavaScript & Why it Matters

另外,为了让您入门,我建议您查看一些入门套件。选择一个符合您对技术堆栈的选择(请记住,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:

  • Create React App

或者从社区中选择其中一个。有一个很好的网站,试图索引所有这些:

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

  • Pick your perfect React starter project

我从这些开始:

  • React Isomorphic Starterkit
  • React Redux Universal Hot Example

目前我正在使用受上述两个入门套件启发的家庭酿造通用渲染版本,但他们现在已经过时了。

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天全站免登陆