我正在使用React-router,当我点击链接按钮时它工作正常,但是当我刷新我的网页时它没有加载我想要的东西 .
例如,我进入localhost / joblist,一切都很好,因为我来到这里按一个链接 . 但是,如果我刷新网页,我得到:不能GET / joblist
默认情况下它不像这样工作 . 最初我有我的URL:localhost /#/和localhost /#/ joblist,他们工作得非常好 . 但我不喜欢这种网址,所以试图抹去我写的'#':
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);
});
30 回答
这里的答案都非常有用,对我来说有用的是配置我的Webpack服务器以期望路由 .
historyApiFallback是我解决这个问题的原因 . 现在路由工作正常,我可以刷新页面或直接输入URL . 无需担心节点服务器上的解决方法 . 这个答案显然只有在你使用webpack时才有效 .
编辑:请在此处查看我的答案,了解为何需要更详细的原因:https://stackoverflow.com/a/37622953/5217568
实际解决方法:
将原始html文件复制并重命名为joblist.html
使用joblist.html作为路径路径
无需服务器端更改 .
我使用create-react-app来制作一个网站,并且在这里提出了相同的问题 . 我使用
react-router-dom
包中的BrowserRouting
. 我在Nginx服务器上运行,为我解决了这个问题,将以下内容添加到/etc/nginx/yourconfig.conf
这对应于在运行Appache时将以下内容添加到
.htaccess
这似乎也是Facebook自己提出的解决方案,可以找到here
In case, anyone is here looking for solution on React JS SPA with Laravel. 接受的答案是对这些问题发生原因的最佳解释 . 如前所述,您必须配置客户端和服务器端 . 在您的刀片模板中,包含js捆绑文件,请确保使用
URL facade
这样在您的路由中,请确保将其添加到刀片模板所在的主 endpoints . 例如,
以上是刀片模板的主要 endpoints . 现在添加一个可选路线,
发生的问题是首先加载刀片模板,然后加载反应路由器 . 因此,当您加载
'/setting-alerts'
时,它会加载html和js . 但是当你加载'/setting-alerts/about'
时,它首先在服务器端加载 . 由于在服务器端,此位置没有任何内容,因此返回未找到 . 当你有这个可选的路由器时,它会加载同一个页面并且反应路由器也被加载,然后反应加载器决定显示哪个组件 . 希望这可以帮助 .使用preact-router进行Preact的解决方案
Works with refresh and direct access
对于那些通过谷歌发现这一点的人来说,这是一个preact-router哈希历史的演示:
https://jsfiddle.net/developit/gLyL6rbn/
If you are using Create React App:
对于许多主要托管平台的解决方案,您可以在Create React App页面上找到HERE,这是一个很好的步骤 . 例如,我使用React Router v4和Netlify作为我的前端代码 . 所需要的只是将1个文件添加到我的公共文件夹("_redirects")和该文件中的一行代码:
现在我的网站在进入浏览器或者某人点击刷新时正确呈现了像mysite.com/pricing这样的路径 .
如果确实有index.html的回退,请确保在index.html文件中有以下内容:
这可能因项目而异 .
如果您在IIS中托管;将此添加到我的webconfig解决了我的问题
您可以为任何其他服务器进行类似配置
我有同样的问题和this解决方案为我们工作..
背景:
我们在同一台服务器上托管多个应用 . 当我们刷新服务器时,不会理解在该特定应用程序的dist文件夹中查找索引的位置 . 上面的链接将带您了解对我们有用的东西......希望这会有所帮助,因为我们花了相当长的时间来找出满足我们需求的解决方案 .
我们正在使用:
我的webpack.config.js
我的index.js
我的app.js
Production stack: React, React Router v4, BrowswerRouter, Express, Nginx
1)用户浏览器路由器的漂亮网址
2)使用
/*
将index.html添加到所有未知请求3)用
webpack -p
捆绑webpack4)运行
nodemon server.js
或node server.js
编辑:你可能想让nginx在服务器块中处理这个并忽略第2步:
将此添加到webpack.congif.js
这可以解决您的问题
我在 生产环境 模式下的ReactJS应用程序中也遇到了同样的问题 . 这是问题的解决方案 .
1.将路由历史记录更改为“hashHistory”而不是browserHistory
现在使用该命令构建应用程序
然后放置在var / www /文件夹中构建文件夹,现在应用程序正常工作,在每个URL中添加了#tag . 喜欢
localhost /#/ home localhost /#/ aboutus
解决方案2:没有使用browserHistory的#tag,
在您的路由器中设置您的history = ,现在使用sudo npm run build构建它 .
您需要创建“conf”文件来解决404未找到的页面,conf文件应该是这样的 .
打开你的终端输入以下命令
cd / etc / apache2 / sites-available ls nano sample.conf在其中添加以下内容 .
现在,您需要使用以下命令启用sample.conf文件
然后它会要求你重新加载apache服务器,使用sudo service apache2 reload或restart
然后打开localhost / build文件夹并添加包含以下内容的.htaccess文件 .
现在该应用程序正常工作 .
注意:将0.0.0.0 ip更改为本地IP地址 .
如果对此有任何疑问,请随时提出评论 .
我希望它对其他人有所帮助 .
如果您在后端使用Express或其他框架,您可以添加如下的类似配置并查看配置中的Webpack公共路径,如果您使用的是BrowserRouter,即使重新加载也应该可以正常工作
我喜欢这种处理方式 . 尝试在服务器端添加: yourSPAPageRoute/* 以解决此问题 .
我采用这种方法,因为即使是原生的HTML5 History API也不支持页面刷新时的正确重定向(据我所知) .
注意:选定的答案已经解决了这个问题,但我想更具体一点 .
Express Route
经过测试,只是想分享一下 .
希望能帮助到你 .
我还没有使用服务器端渲染,但是我遇到了与OP相同的问题,其中Link似乎大部分时间工作正常,但是当我有一个参数时失败了 . 我会在这里记录我的解决方案,看看它是否有助于任何人 .
我的主要jsx包含这个:
这适用于第一个匹配的链接,但是当嵌套在该模型的详细信息页面上的
<Link>
表达式中的:id更改时,URL会在浏览器栏中更改,但页面内容最初不会更改以反映链接的模型 .问题是我使用
props.params.id
在componentDidMount
中设置了模型 . 组件刚刚安装一次,这意味着第一个模型是粘在页面上的模型,随后的链接会更改道具,但保持页面不变 .在
componentDidMount
和componentWillReceiveProps
(它基于下一个道具)中的组件状态中设置模型可以解决问题,并且页面内容会发生变化以反映所需的模型 .如果您在IIS上托管您的react应用程序,只需添加一个包含以下内容的web.config文件:
这将告诉IIS服务器将主页面返回到客户端而不是404错误,并且不需要使用哈希历史记录 .
对于那些使用IIS 10的人来说,这就是你应该做的事情 . 请确保您使用的是browserHistory . 至于参考,我将给出路由的代码,但这不重要,重要的是下面的组件代码之后的下一步:
由于问题是IIS从客户端浏览器接收请求,它会将URL解释为要求页面,然后返回404页面,因为没有可用页面 . 请执行下列操作:
打开IIS
展开服务器,然后打开“站点文件夹”
单击网站/应用程序
转到错误页面
打开列表中的404错误状态项
而不是选项"Insert content from static file into the error response",将其更改为"Execute a URL on this site"并将"/"斜杠值添加到URL .
它现在可以正常工作了 .
我希望它有所帮助 . :-)
这个主题有点陈旧和解决但我想建议你一个简单,明确和更好的解决方案 . 如果您使用Web服务器,它可以工作 .
在http 404的情况下,每个Web服务器都能够将用户重定向到错误页面 . 要解决此问题,您需要将用户重定向到索引页面 .
如果您使用Java基本服务器(tomcat或任何Java应用程序服务器),解决方案可能如下:
web.xml:
例:
GET http://example.com/about
Web服务器抛出http 404,因为服务器端不存在此页面
错误页面配置告诉服务器将index.jsp页面发送回用户
然后JS将在客户端执行剩余的工作,因为客户端的URL仍然是http://example.com/about .
就是这样,没有更多魔法需要:)
尝试使用以下代码在公用文件夹中添加“.htaccess”文件 .
如果你正在使用firebase,你所要做的就是确保你的应用程序根目录中的firebase.json文件中有一个重写属性(在托管部分) .
例如:
希望这可以为其他人节省挫折和浪费时间 .
快乐的编码......
进一步阅读该主题:
https://firebase.google.com/docs/hosting/full-config#rewrites
Firebase CLI: "Configure as a single-page app (rewrite all urls to /index.html)"
If you're hosting a react app via AWS Static S3 Hosting & CloudFront
这个问题由CloudFront以403 Access Denied消息响应,因为它预期/某些/其他/路径存在于我的S3文件夹中,但该路径仅存在于React与react-router的路由中 .
解决方案是设置分发错误页面规则 . 转到CloudFront设置并选择您的分发 . 接下来转到“错误页面”选项卡 . 单击“创建自定义错误响应”并为403添加条目,因为这是我们获得的错误状态代码 . 将响应页面路径设置为/index.html,将状态代码设置为200.最终结果令我惊讶于它的简单性 . 提供了索引页面,但URL保留在浏览器中,因此一旦反应应用程序加载,它将检测URL路径并导航到所需的路径 .
Error Pages 403 Rule
这里有很多好的答案,不需要在这里写出更多的答案 .
但是,我在这里提供另一个好的链接
https://css-tricks.com/learning-react-router/#article-header-id-9
可以通过两种不同的方式调用路由器,具体取决于导航是在客户端还是在服务器上进行 . 您已将其配置为客户端操作 . 关键参数是run method的第二个位置 .
当您使用React Router Link组件时,它会阻止浏览器导航并调用transitionTo来执行客户端导航 . 您正在使用HistoryLocation,因此它使用HTML5历史记录API通过模拟地址栏中的新URL来完成导航错觉 . 如果您使用的是较旧的浏览器,则无法使用 . 您需要使用HashLocation组件 .
当您点击刷新时,您将绕过所有React和React路由器代码 . 服务器获取
/joblist
的请求,它必须返回一些东西 . 在服务器上,您需要将请求的路径传递给run
方法,以便呈现正确的视图 . 您可以使用相同的路线图,但您可能需要对Router.run
进行不同的调用 . 正如Charles指出的那样,您可以使用URL重写来处理这个问题 . 另一种选择是使用node.js服务器来处理所有请求,并将路径值作为location参数传递 .例如,在express中,它可能如下所示:
请注意,请求路径正在传递给
run
. 要做到这一点,您需要有一个服务器端视图引擎,您可以将呈现的HTML传递给 . 使用renderToString
以及在服务器上运行React时还有许多其他注意事项 . 在服务器上呈现页面后,当您的应用程序加载到客户端时,它将再次呈现,根据需要更新服务器端呈现的HTML .你可以改变你的htaccess并插入:
我正在使用
react: "^15.3.2"
,react-router: "^3.0.0"
,history: "^4.3.0"
,在index.html
head
中,添加以下内容:然后在使用webpack dev server运行时使用此命令 .
--history-api-fallback
是重要的部分对于 React Router V4 用户:
如果您尝试通过其他答案中提到的哈希历史技术解决此问题,请注意
<Router history={hashHistory} >
在V4中不起作用,请改用
HashRouter
:参考:https://reacttraining.com/react-router/web/api/HashRouter
看看对已接受答案的评论和这个问题的一般性质(“不工作”),我认为这可能是对这里涉及的问题进行一些一般性解释的好地方 . 因此,这个答案旨在作为OP的具体用例的背景信息/详细说明 . 请多多包涵 .
服务器端与客户端
要理解这一点的第一件大事是,现在有2个地方解释了URL,而在'the old days'中只有1个 . 在过去,当生活很简单时,一些用户向服务器发送了
http://example.com/about
的请求,该服务器检查了URL的路径部分,确定用户正在请求about页面然后发回该页面 .使用React-Router提供的客户端路由,事情就不那么简单了 . 起初,客户端尚未加载任何JS代码 . 所以第一个请求将永远是服务器 . 然后,它将返回一个页面,其中包含所需的脚本标记以加载React和React Router等 . 只有当这些脚本加载时才会启动第2阶段 . 在阶段2中,例如,当用户单击'About us'导航链接时,URL仅在本地更改为
http://example.com/about
(由History API实现),但是 no request to the server is made . 相反,React Router已经完成了'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' . 您已经从Home转换为About Us而没有任何服务器请求被解雇 .因此,基本上当您单击链接时,会运行一些Javascript来操作地址栏中的URL,而不会导致页面刷新,从而导致React Router执行页面转换 on the client side .
但现在考虑如果您将URL复制粘贴到地址栏并通过电子邮件发送给朋友,会发生什么 . 您的朋友尚未加载您的网站 . 换句话说,她仍处于第1阶段 . 尚未在她的机器上运行React Router . 所以她的浏览器会将 server request 设为
http://example.com/about
.这就是你的麻烦所在开始 . 到目前为止,只需在服务器的webroot上放置一个静态HTML即可 . 但是,当从服务器请求时,这将为所有其他URL提供
404
错误 . 这些相同的URL在客户端工作正常,因为React Router正在为您执行路由,但它们在服务器端失败,除非您让服务器理解它们 .结合服务器端和客户端路由
如果您希望
http://example.com/about
URL在服务器端和客户端都可以工作,则需要在服务器端和客户端为它设置路由 . 有道理吗?这就是你的选择开始的地方 . 解决方案包括完全绕过问题,通过返回引导HTML的全能路由,以及服务器和客户端运行相同JS代码的全面同构方法 .
.
完全绕过问题:哈希历史
使用Hash History而不是Browser History,about页面的URL将如下所示:
http://example.com/#/about
散列(#
)符号后面的部分未发送到服务器 . 因此服务器只能看到http://example.com/
并按预期发送索引页面 . React-Router将获取#/about
部分并显示正确的页面 .Downsides :
'ugly'个网址
使用此方法无法进行服务器端呈现 . 就搜索引擎优化(SEO)而言,您的网站由一个页面组成,几乎没有任何内容 .
.
Catch-all
使用这种方法,您可以使用浏览器历史记录,但只需在服务器上设置一个catch-all,将
/*
发送到index.html
,从而有效地为您提供与哈希历史记录相同的情况 . 但是,您确实拥有干净的URL,您可以在以后改进此方案,而不必使用户的所有收藏夹无效 .Downsides :
设置起来比较复杂
仍然没有好的SEO
.
混合动力车
在混合方法中,您可以通过为特定路由添加特定脚本来扩展catch-all场景 . 您可以制作一些简单的PHP脚本来返回包含内容的网站中最重要的页面,因此Googlebot至少可以查看您网页上的内容 .
Downsides :
设置起来更复杂
对于那些给予特殊待遇的路线,只有优秀的搜索引擎优化
复制用于在服务器和客户端上呈现内容的代码
.
同构
如果我们使用Node JS作为我们的服务器,那么我们可以在两端运行相同的JS代码怎么办?现在,我们已经在一个反应路由器配置中定义了所有路由,可以说我们不知道圣杯 . 如果在客户端上发生页面转换,服务器将发送完全相同的标记 . 该解决方案在SEO方面是最佳的 .
Downsides :
服务器必须(能够)运行JS . 我've experimented with Java i.c.w. Nashorn but it'不适合我 . 在实践中,它主要意味着您必须使用基于Node JS的服务器 .
许多棘手的环境问题(在服务器端使用
window
等)陡峭的学习曲线
.
我应该使用哪个?
选择你可以逃脱的那个 . 就我个人而言,我认为这个包罗万象足够简单,可以设置出最低限度 . 此设置允许您随着时间的推移改进 . 如果您已经使用Node JS作为服务器平台,我肯定会调查做同构应用程序 . 是的,一开始很难,但一旦掌握了它,它实际上是解决问题的一个非常优雅的解决方案 .
所以基本上,对我来说,这将是决定性的因素 . 如果我的服务器在Node JS上运行,我会变得同构,否则我会选择Catch-all解决方案并随着时间的推移扩展它(混合解决方案)并且SEO要求它 .
如果您想了解有关使用React进行同构(也称为“通用”)渲染的更多信息,可以参考以下主题:
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本身发布的那个:
或者从社区中挑选其中一个 . 现在有一个很好的网站试图索引所有这些:
我从这些开始:
React Isomorphic Starterkit
React Redux Universal Hot Example
目前我使用的是通用渲染的家庭酿造版本,其灵感来自上面的两个入门套件,但它们现在已经过时了 .
祝你好运!
它很简单,当你得到刷新dom组件后无法获得403错误 . 只需在您的web pack配置中添加这一行,'historyApiFallback:true' . 这节省了我整整一天 .
-jimbotron的评论帮助了我,问题是.htaccess
'这是帮助解决我的问题的参考:https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#serving-apps-with-client-side-routing - jimbotron'
Webpack Dev Server有一个选项来启用它 . 打开
package.json
并添加--history-api-fallback
. 这个解决方案对我有用 .https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls#configuring-your-server