我正在使用React-router,当我点击链接按钮时它工作正常,但是当我刷新我的网页时,它没有加载我想要的内容。
例如,我在localhost/joblist
,一切都很好,因为我来到这里按一个链接。但如果我刷新网页,我会得到:
Cannot GET /joblist
默认情况下,它没有像这样工作。最初我将我的网址设为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);
});
答案 0 :(得分:789)
看看对已接受答案的评论以及这个问题的一般性质(不工作&#39;),我认为这可能是一个关于一些一般性解释的好地方这里涉及的问题。因此,这个答案旨在作为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视图。假设您的about页面不需要进行任何REST调用,那么它已经完成了。您已经从Home转换为About Us而没有任何服务器请求被解雇。
所以基本上当你点击一个链接时,会运行一些Javascript来操纵地址栏中的URL,而不会导致页面刷新,这反过来会导致React Router执行页面转换在客户端。
但现在考虑如果您将地址栏中的URL复制粘贴并通过电子邮件发送给朋友会发生什么。您的朋友尚未加载您的网站。换句话说,她仍处于阶段1 。没有React Router正在她的机器上运行。因此,她的浏览器会向http://example.com/about
发出服务器请求。
这就是你的麻烦开始的地方。到目前为止,只需在服务器的webroot上放置静态HTML即可。但是,当从服务器请求时,这会给所有其他URL 带来404
错误。这些相同的URL在客户端上工作正常,因为React Router正在为您执行路由,但它们在服务器端上失败,除非您让服务器理解它们。
如果您希望http://example.com/about
URL在服务器端和客户端都可以工作,则需要在服务器端和客户端为它设置路由。有道理吗?
这就是你的选择开始的地方。解决方案包括完全绕过问题,通过返回引导HTML的全能路由,以及服务器和客户端运行相同JS代码的全面同构方法。
使用Hash History代替Browser History,about页面的网址如下所示:
http://example.com/#/about
散列(#
)符号后面的部分不会发送到服务器。因此服务器只看到http://example.com/
并按预期发送索引页。 React-Router将选择#/about
部分并显示正确的页面。
下行:
使用这种方法,您可以使用浏览器历史记录,但只需在将/*
发送到index.html
的服务器上设置一个包罗万象,有效地为您提供与哈希历史记录相同的情况。但是,您确实拥有干净的网址,您可以稍后改进此计划,而不必使用户的所有收藏失效。
下行:
在混合方法中,您可以通过为特定路由添加特定脚本来扩展catch-all场景。您可以制作一些简单的PHP脚本来返回包含内容的网站中最重要的页面,因此Googlebot至少可以查看您网页上的内容。
<强>缺点强>:
如果我们使用Node JS作为我们的服务器,那么我们可以在两端运行相同的 JS代码怎么办?现在,我们在单个react-router配置中定义了所有路由,并且我们不需要复制渲染代码。这是圣杯&#39;可以这么说。如果在客户端上发生页面转换,服务器将发送完全相同的标记。这个解决方案在SEO方面是最佳的。
<强>缺点强>:
window
等)
选择您可以逃脱的那个。就我个人而言,我觉得这一切都足够简单,所以这将是我的最低限度。此设置允许您随着时间的推移改进。如果您已经使用Node JS作为服务器平台,我肯定会调查做同构应用程序。是的,一开始很难,但是一旦掌握了它,它实际上是解决问题的一个非常优雅的解决方案。
所以基本上,对我来说,这将是决定因素。如果我的服务器在Node JS上运行,我会变得同构;否则我会选择Catch-all解决方案并随着时间的推移扩展它(混合解决方案)并且SEO要求它。
如果您想了解更多有关使用React进行同构(也称为“通用&#39;”渲染)的更多信息,可以参考以下主题:
另外,为了帮助您入门,我建议您查看一些入门套件。选择一个符合您对技术堆栈的选择(请记住,React只是MVC中的V,您需要更多东西来构建完整的应用程序)。首先看看Facebook本身发布的那个:
或者从社区中挑选其中一个。现在有一个很好的网站试图索引所有这些网站:
我从这些开始:
目前我使用的是通用渲染的家庭酿造版本,其灵感来自上面的两个入门套件,但它们现在已经过时了。
祝你好运!
答案 1 :(得分:91)
这里的答案都非常有用,对我来说有用的是配置我的Webpack服务器以期望路由。
devServer: {
historyApiFallback: true,
contentBase: './',
hot: true
},
historyApiFallback是解决这个问题的原因。现在路由工作正常,我可以刷新页面或直接输入URL。无需担心节点服务器上的解决方法。这个答案显然只有在您使用webpack时才有效。
编辑:请在此处查看我的答案,了解为何需要这样做的更详细原因: https://stackoverflow.com/a/37622953/5217568
答案 2 :(得分:43)
React Router V4 用户:
如果您尝试通过其他答案中提到的哈希历史记录技术解决此问题,请注意
<Router history={hashHistory} >
在V4中不起作用,请改为使用HashRouter
:
import { HashRouter } from 'react-router-dom'
<HashRouter>
<App/>
</HashRouter>
参考: https://reacttraining.com/react-router/web/api/HashRouter
答案 3 :(得分:41)
您可以更改htaccess并插入:
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
我正在使用react: "^15.3.2"
,react-router: "^3.0.0"
,history: "^4.3.0"
,
答案 4 :(得分:27)
可以通过两种不同的方式调用路由器,具体取决于导航是在客户端还是在服务器上进行。您已将其配置为客户端操作。关键参数是run method的第二个参数,即位置。
当您使用React Router Link组件时,它会阻止浏览器导航并调用transitionTo来执行客户端导航。您正在使用HistoryLocation,因此它使用HTML5历史记录API通过模拟地址栏中的新URL来完成导航错觉。如果您使用的是较旧的浏览器,则无法使用。您需要使用HashLocation组件。
点击刷新后,您将绕过所有React和React路由器代码。服务器获取/joblist
的请求,它必须返回一些内容。在服务器上,您需要将请求的路径传递给run
方法,以便呈现正确的视图。您可以使用相同的路线图,但您可能需要对Router.run
进行不同的调用。正如Charles指出的那样,您可以使用URL重写来处理这个问题。另一种选择是使用node.js服务器来处理所有请求,并将路径值作为location参数传递。
例如,在快递中,它可能如下所示:
var app = express();
app.get('*', function (req, res) { // This wildcard method handles all requests
Router.run(routes, req.path, function (Handler, state) {
var element = React.createElement(Handler);
var html = React.renderToString(element);
res.render('main', { content: html });
});
});
请注意,请求路径正在传递给run
。要做到这一点,您需要有一个服务器端视图引擎,您可以将呈现的HTML传递给。使用renderToString
和在服务器上运行React时还有许多其他注意事项。一旦页面在服务器上呈现,当您的应用程序在客户端加载时,它将再次呈现,根据需要更新服务器端呈现的HTML。
答案 5 :(得分:19)
在index.html head
中,添加以下内容:
<base href="/">
<!-- This must come before the css and javascripts -->
然后在使用webpack dev server运行时使用此命令。
webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback
--history-api-fallback
是重要的部分
答案 6 :(得分:14)
Webpack Dev Server可以选择启用此功能。打开package.json
并添加--history-api-fallback
。
这个解决方案对我有用。
答案 7 :(得分:13)
我刚刚使用create-react-app创建了一个网站,并在此处提出了相同的问题。我使用BrowserRouting
包中的react-router-dom
。我在Nginx服务器上运行,为我解决的是将以下内容添加到/etc/nginx/yourconfig.conf
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.html break;
}
}
对应于在运行Appache
时将以下内容添加到.htaccess
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
这似乎也是Facebook自己提出的解决方案,可以找到here
答案 8 :(得分:12)
如果您通过AWS Static S3 Hosting&amp ;;托管反应应用程序CloudFront的强>
此问题由CloudFront以403 Access Denied消息响应,因为它预期/某些/其他/路径存在于我的S3文件夹中,但该路径仅存在于React与react-router的路由中。
解决方案是设置分发错误页面规则。转到CloudFront设置并选择您的分发。接下来转到“错误页面”选项卡。单击“创建自定义错误响应”并为403添加条目,因为这是我们获得的错误状态代码。将响应页面路径设置为/index.html,将状态代码设置为200.最终结果令我惊讶于它的简单性。提供了索引页面,但URL保留在浏览器中,因此一旦反应应用程序加载,它将检测URL路径并导航到所需的路径。
答案 9 :(得分:12)
这可以解决您的问题
我在生产模式下的ReactJS应用程序中也遇到了同样的问题。 这是问题的解决方案。
1.将路由历史记录更改为“hashHistory”而不是browserHistory代替
customClass="MyOldControllerName"
现在使用命令
构建应用程序customClass="MyNewControllerName"
然后将构建文件夹放在var / www /文件夹中,现在应用程序正常工作,并在每个URL中添加#tag。喜欢
本地主机/#/家 本地主机/#/公司简介
解决方案2:没有#tag使用browserHistory,
在路由器中设置历史记录= {browserHistory},现在使用sudo npm run build构建它。
您需要创建“conf”文件来解决404未找到的页面, conf文件应该是这样的。
打开你的终端输入以下命令
cd / etc / apache2 / sites-available LS nano sample.conf 在其中添加以下内容。
<Router history={hashHistory} >
<Route path="/home" component={Home} />
<Route path="/aboutus" component={AboutUs} />
</Router>
现在需要使用以下命令启用sample.conf文件
sudo npm run build
然后它会要求你重新加载apache服务器,使用 sudo service apache2 reload or restart
然后打开localhost / build文件夹并添加.htaccess文件,其中包含以下内容。
<VirtualHost *:80>
ServerAdmin admin@0.0.0.0
ServerName 0.0.0.0
ServerAlias 0.0.0.0
DocumentRoot /var/www/html/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory "/var/www/html/">
Options Indexes FollowSymLinks
AllowOverride all
Require all granted
</Directory>
</VirtualHost>
现在应用程序正常运行。
注意:将0.0.0.0 ip更改为本地IP地址。
如果对此有任何疑问,请随时提出评论。
我希望它对其他人有所帮助。
答案 10 :(得分:8)
生产堆栈:React,React Router v4,BrowswerRouter,Express,Nginx
1)针对漂亮网址的用户浏览器
// app.js
import { BrowserRouter as Router } from 'react-router-dom'
const App = () {
render() {
return (
<Router>
// your routes here
</Router>
)
}
}
2)使用/*
// server.js
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})
3)将webpack与webpack -p
4)运行nodemon server.js
或node server.js
编辑:你可能想让nginx在服务器块中处理这个并忽略第2步:
location / {
try_files $uri /index.html;
}
答案 11 :(得分:8)
将此添加到webpack.congif.js
devServer: {
historyApiFallback: true
}
答案 12 :(得分:6)
尝试使用以下代码在公用文件夹内添加“ .htaccess”文件。
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html [L]
答案 13 :(得分:5)
如果您使用的是Create React App:
对于许多主要托管平台的解决方案,您可以在Create React App页面上找到HERE,这是一个很好的解决方案。例如,我使用React Router v4和Netlify作为我的前端代码。所需要的只是将1个文件添加到我的公共文件夹(&#34; _redirects&#34;)和该文件中的一行代码:
/* /index.html 200
现在,我的网站在进入浏览器或有人点击刷新时正确呈现了像mysite.com/pricing这样的路径。
答案 14 :(得分:3)
这个主题有点陈旧并且已经解决,但我想建议一个简单,清晰和更好的解决方案。如果您使用Web服务器,它可以工作。
每个Web服务器都能够在http 404的情况下将用户重定向到错误页面。要解决此问题,您需要将用户重定向到索引页。
如果您使用Java基本服务器(tomcat或任何Java应用程序服务器),解决方案可能如下:
<强>的web.xml:强>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- WELCOME FILE LIST -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- ERROR PAGES DEFINITION -->
<error-page>
<error-code>404</error-code>
<location>/index.jsp</location>
</error-page>
</web-app>
示例:
就是这样,没有更多魔法需要:)
答案 15 :(得分:3)
如果您在IIS上托管您的react应用程序,只需添加一个包含以下内容的web.config文件:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
</configuration>
这将告诉IIS服务器将主页面返回给客户端而不是404错误,并且不需要使用哈希历史记录。
答案 16 :(得分:2)
我找到了带有React Router(Apache)的SPA解决方案。只需添加.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>
来源:https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042
答案 17 :(得分:2)
使用$v1 = null;
echo (isset($v1) ? '$v1 set' : '$v1 not set') . PHP_EOL;
echo (is_null($v1) ? '$v1 null' : '$v1 not null') . PHP_EOL;
echo (empty($v1) ? '$v1 empty' : '$v1 not empty') . PHP_EOL;
echo (array_key_exists('v1', get_defined_vars()) ? '$v1 defined' : '$v1 not defined') . PHP_EOL;
echo PHP_EOL;
echo (isset($v2) ? '$v2 set' : '$v2 not set') . PHP_EOL;
echo (@is_null($v2) ? '$v2 null' : '$v2 not null') . PHP_EOL;
echo (empty($v2) ? '$v2 empty' : '$v2 not empty') . PHP_EOL;
echo (array_key_exists('v2', get_defined_vars()) ? '$v2 defined' : '$v2 not defined') . PHP_EOL;
对 Redux 也很有效,只需替换:
$v1 not set
$v1 null
$v1 empty
$v1 defined
$v2 not set
$v2 null
$v2 empty
$v2 not defined
收件人:
array_key_exists(..., get_defined_vars())
答案 18 :(得分:2)
已经非常棒的答案了!!但是,如果您使用 nginx 托管并且需要快速修复... 将以下行添加到您的 nginx 配置中的 location 块
location / {
try_files $uri /index.html;
}
答案 19 :(得分:2)
如果您使用的是Firebase,则只需确保在应用程序根目录(在托管部分中)的firebase.json文件中具有rewrites属性。
例如:
{
"hosting": {
"rewrites": [{
"source":"**",
"destination": "/index.html"
}]
}
}
希望这可以节省其他人的挫败感和时间浪费。
快乐的编码...
有关该主题的进一步阅读:
https://firebase.google.com/docs/hosting/full-config#rewrites
Firebase CLI: "Configure as a single-page app (rewrite all urls to /index.html)"
答案 20 :(得分:2)
我还没有使用服务器端渲染,但是我遇到了与OP相同的问题,其中Link似乎在大多数情况下工作正常但在我有参数时失败了。我会在这里记录我的解决方案,看看它是否有助于任何人。
我的主要jsx包含:
<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />
这适用于第一个匹配的链接但是当{id}更改嵌套在该模型的详细信息页面上的<Link>
表达式时,网址中的网址会发生变化,但页面的内容却没有最初改变以反映链接的模型。
问题在于我使用props.params.id
在componentDidMount
中设置模型。组件刚刚安装一次,这意味着第一个模型是粘在页面上的模型,随后的链接会更改道具,但让页面保持不变。
在componentDidMount
和componentWillReceiveProps
(基于下一个道具)中的组件状态中设置模型可以解决问题,并且页面内容会发生变化以反映所需的模型。
答案 21 :(得分:2)
如果确实有index.html的后备,请确保在index.html文件中有这个:
<script>
System.config({ baseURL: '/' });
</script>
这可能因项目而异。
答案 22 :(得分:1)
如果您在IIS中托管;将此添加到我的webconfig解决了我的问题
.profile-img-container img:hover {
opacity: 0.5
}
您可以为任何其他服务器进行类似配置
答案 23 :(得分:1)
如果您使用的是“ create-react-app”命令,
要生成一个React应用程序,则package.json需要进行一次更改,以便在浏览器中正确运行生产版本的React SPA。打开package.json并在其中添加以下代码段,
"start": "webpack-dev-server --inline --content-base . --history-api-fallback"
最重要的部分是“ --history-api-fallback”,用于启用历史记录API回调。
如果您使用Spring或任何其他后端API,有时会收到404错误。因此,在这种情况下,您需要在后端有一个控制器,以将任何请求(所需的)转发到index.html文件以由react-router处理。下面演示使用spring编写的示例控制器。
@Controller
public class ForwardingController {
@RequestMapping("/<any end point name>/{path:[^\\.]+}/**")
public String forward(HttpServletRequest httpServletRequest) {
return "forward:/";
}
}
例如,如果我们将后端API REST端点作为“ abc”(http:// localhost:8080 / abc / **),则到达该端点的任何请求都将重定向到响应应用程序(index.html文件) ),然后react-router会处理这些后遗症。
答案 24 :(得分:1)
当我使用.Net Core MVC时,这样的东西对我有所帮助:
public class HomeController : Controller
{
public IActionResult Index()
{
var url = Request.Path + Request.QueryString;
return App(url);
}
[Route("App")]
public IActionResult App(string url)
{
return View("/wwwroot/app/build/index.html");
}
}
基本上在MVC端,所有不匹配的路由都将归入Home/Index
中指定的startup.cs
中。在Index
内部,可以获取原始请求url并将其传递到任何需要的地方。
startup.cs
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
答案 25 :(得分:1)
在我的情况下,当我在其中使用参数时,网址没有加载。
作为快速修复,我添加
<base href="<yourdomain/IP>"></base>
在 build 文件夹中 index.html 文件的标签下。
这刚好解决了我的问题。
答案 26 :(得分:1)
如果有人在这里寻找使用Laravel的React JS SPA的解决方案。
接受的答案是对这些问题发生原因的最佳解释。如前所述,您必须配置客户端和服务器端。
在您的刀片模板中,包含js捆绑文件,请务必使用URL facade
这样的
<script src="{{ URL::to('js/user/spa.js') }}"></script>
在您的路由中,请确保将其添加到刀片模板所在的主端点。例如,
Route::get('/setting-alerts', function () {
return view('user.set-alerts');
});
以上是刀片模板的主要终结点。现在也添加一个可选路线,
Route::get('/setting-alerts/{spa?}', function () {
return view('user.set-alerts');
});
发生的问题是首先加载刀片模板,然后加载反应路由器。因此,当您加载'/setting-alerts'
时,它会加载html和js。但是当你加载'/setting-alerts/about'
时,它首先在服务器端加载。由于在服务器端,此位置没有任何内容,因此返回未找到。如果你有这个可选的路由器,它会加载同一个页面并且反应路由器也被加载,然后反应加载器决定显示哪个组件。
希望这会有所帮助。
答案 27 :(得分:1)
如果你在后端使用Express或其他框架,你可以添加如下的类似配置并查看配置中的Webpack公共路径,如果你使用的是BrowserRouter,它应该可以很好地重新加载
` expressApp.get('/*', (request, response) => {
response.sendFile(path.join(__dirname, '../public/index.html'));
});`
答案 28 :(得分:0)
我知道这个问题已经死了,但它并不能解决您要通过代理传递使用浏览器路由器而不能使用root的问题。
对我来说,解决方案非常简单。
假设您的网址指向某个端口。
location / {
proxy_pass http://127.0.0.1:30002/;
proxy_set_header Host $host;
port_in_redirect off;
}
,现在由于浏览器路由器,子路径已损坏。但是,您知道什么是子路径。
解决方案?对于子路径/contact
# just copy paste.
location /contact/ {
proxy_pass http://127.0.0.1:30002/;
proxy_set_header Host $host;
}
我没有尝试过其他任何方法,但是这个简单的修复方法就像该死的魅力。
答案 29 :(得分:0)
我正在使用React.js + Webpack模式。我在--history-api-fallback
文件中添加了package.json
参数。然后页面刷新工作正常。
每次更改代码时,网页都会自动刷新。
"scripts": {
"start": "rimraf build && cross-env NODE_ENV='development' webpack --mode development && cross-env NODE_ENV=development webpack-dev-server --history-api-fallback",
...
}
答案 30 :(得分:0)
HashRouter 将是一个简单的实现,
import {HashRouter as Router,Switch,Route,Link} from 'react-router-dom';
function App() {
return (
<Router>
<Switch>
<Route path="/" exact component={InitialComponent} />
<Route path="/some" exact component={SomeOtherComponent} />
</Switch>
</Router>
);
}
在浏览器中会是这样的—— http:localhost:3000/#/ , http:localhost:3000/#/some
答案 31 :(得分:0)
在具有到达/路由器的后端上使用Express并在前端使用React(不带react-create-app),将显示正确的到达/路由器路由react组件,并在按Enter键时将菜单链接设置为活动样式地址栏,例如http:// localhost:8050 / pages。请在下面结帐,或直接转到我的仓库https://github.com/nickjohngray/staticbackeditor,所有代码都在这里。
Webpack :
设置代理。这允许从端口3000(React)进行的任何调用来调用服务器 包括按下Enter键时调用index.html或地址栏中任何内容的调用。它还允许调用API路由以获取JSON数据
就像等待axios.post('/ api / login',{email,pwd})
devServer: {
port: 3000,
open: true,
proxy: {
'/': 'http://localhost:8050',
}
}
设置快速路线
app.get('*', (req, res) => {
console.log('sending index.html')
res.sendFile(path.resolve('dist', 'index.html'))
});
这将匹配任何来自react的请求, 它只是返回index.html页面,该页面位于我的dist文件夹中 当然,此页面还有一个单页面的React应用。 (请注意,其他路线也应显示在此上方,在我的情况下,这是我的API路线)
反应路线
<Router>
<Home path="/" />
<Pages path="pages"/>
<ErrorPage path="error"/>
<Products path="products"/>
<NotFound default />
</Router>
这些路线是在我的Layout组件中定义的,当路径匹配时,它们将加载相应的组件。
反应式布局构造函数
constructor(props) {
super(props);
this.props.changeURL({URL: globalHistory.location.pathname});
}
布局构造函数在加载后立即被调用。在这里,我将我的菜单侦听的redux action changeURL称为菜单URL,以便它可以突出显示正确的菜单项,如下所示:
菜单代码
<nav>
{this.state.links.map( (link) =>
<Link className={this.getActiveLinkClassName(link.path) } to={link.path}>
{link.name}
</Link>)}
</nav>
答案 32 :(得分:0)
对于那些因为试图从IIS虚拟目录(而不是网站的根目录)提供React应用而在这里的人来说,这可能适合您。
设置重定向时,'/'不能单独工作,对我来说,它也需要在其中使用虚拟目录名称。这是我的网络配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<defaultDocument>
<files>
<remove value="default.aspx" />
<remove value="iisstart.htm" />
<remove value="index.htm" />
<remove value="Default.asp" />
<remove value="Default.htm" />
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/YOURVIRTUALDIRECTORYNAME/" />
</rule>
</rules>
</rewrite>
<directoryBrowse enabled="false" />
<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
<remove statusCode="500" subStatusCode="100" />
<remove statusCode="500" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="403" subStatusCode="18" />
<error statusCode="403" subStatusCode="18" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
<error statusCode="404" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
<error statusCode="500" prefixLanguageFilePath="" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
<error statusCode="500" subStatusCode="100" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
</configuration>
除了web.config文件之外,React应用本身还需要进行一些更改:
在package.json中,您需要添加一个“主页”条目:
{
"name": "sicon.react.crm",
"version": "0.1.0",
"private": true,
"homepage": "/YOURVIRTUALDIRECTORYNAME/",
"dependencies": {
...
我将基本名称添加到我的浏览器历史记录对象中,该对象传递给路由器以访问历史记录:
import {createBrowserHistory } from 'history';
export default createBrowserHistory({
//Pass the public URL as the base name for the router basename: process.env.PUBLIC_URL
});
我还在App.js的React路由器上添加了此属性:
<Router history={history} basename={process.env.PUBLIC_URL}>
最后,在index.html中,我在“标题”标签上方添加了以下标签
<base href="%PUBLIC_URL%/">
可能需要一些步骤,但需要注意,但这似乎已经为我完成了工作。我不知道如何将其设置为在网站的根目录或虚拟目录中运行,而无需重新编译,尽管package.json
中的主页在生成后无法交换到我为止。我知道。
答案 33 :(得分:0)
当我使用 React 作为前端和使用 react-router-dom
进行路由时,我在 Electron 中遇到了这个问题。
我用 BrowserRouter
替换了 HashRouter
并修复了它。
这是一个简单的例子
import {
HashRouter as Router,
Switch,
Route,
} from "react-router-dom";
答案 34 :(得分:0)
如果您在Google Bucket上运行它,简单的解决方案是考虑使用“ index.html”查找错误(找不到404页)。
要这样做:
答案 35 :(得分:0)
即使您立即直接指向url,请求数据的另一种方法是使每个组件都具有一种方法,该方法调用最后一个参数,例如/ about / test ,然后调用您的State Provider。具有使用
连接到您要请求数据的组件的功能答案 36 :(得分:0)
我通过更改webpack.config.js解决了这个问题。
我的新配置如下:
之前:
output: {
path: path.join(__dirname, '/build/static/js'),
filename: 'index.js'
},
devServer: {
port: 3000
}
之后:
output: {
path: path.join(__dirname, '/build/static/js'),
filename: 'index.js',
publicPath: '/'
},
devServer: {
historyApiFallback: true,
port: 3000
}
答案 37 :(得分:0)
您可以尝试阅读所有内容,尽管这不是我的:
https://www.andreasreiterer.at/fix-browserrouter-on-apache/
修复应用的路由 现在,这是最终解决路由的方法。为了告诉Apache将请求重定向到应用程序所在的index.html,我们必须修改.htaccess文件。如果您的应用文件夹中还没有此类文件,则只需创建它即可。
然后确保您输入的这4行将神奇地使您的路由工作。
s = cumsum(VItimeseries,1); % cumulative sum explicitly along columns
s2 = cumsum(VItimeseries.^2,1);
n = (1:size(VItimeseries,1)).'; % use number of rows, rather than `numel`.
v = (s2 - s.^2 ./ n) ./ (n-1);
v(1,:) = 0; % fill first row with zeros, not just first element
将.htaccess文件放入与index.html相同的目录后,Apache会将每个新请求直接重定向到您的应用。
奖金:将React应用程序部署到子目录
如果您要将应用程序部署到子目录中,则可以访问它,例如通过https://myapp.com/the-app,您很快就会发现还有另一个问题。每次点击新路径都会将URL转换为https://myapp.com/route-abc之类的内容-重新加载后将再次中断。但是有一个简单的解决方法:
BrowserRouter有一个名为basename的属性,您可以在其中指定子目录路径:
从现在开始,每条路线(如/ contacts)都将产生类似http://myapp.com/the-app/contacts的URL。
答案 38 :(得分:0)
我们使用了express' 404 handling approach
import math
def readFileIntoAList(file,N):
lines= list()
lines1 = list()
with open(file) as f:
lines1 = [lineNew.rstrip("\n") for lineNew in f]
for a in range(math.ceil(len(lines1)/N)):
lines.append((*lines1[a*N:(a+1)*N],))
return lines
像魅力一样工作。现场演示是our site
答案 39 :(得分:0)
这是我发现的前端解决方法,不需要修改服务器上的任何内容。
假设您的网站是mysite.com,并且您有一个通往mysite.com/about的React Route。 在index.js中,您在其中安装了顶级组件,可以放置另一个路由器,例如:
ReactDOM.render(
<Router>
<div>
<Route exact path="/" component={Home} />
<Route exact path="/about"
render={(props) => <Home {...props} refreshRout={"/about"}/>}
/>
</div>
</Router>,
我假设您的原始路由器位于虚拟DOM的顶级组件下方的某个位置。如果您使用的是Django,则还必须在.urls中捕获该URL:
urlpatterns = [
path('about/', views.index),
]
这将取决于您使用的后端。请求mysite / about将带您进入index.js(在其中安装顶级组件),您可以在其中使用Route的渲染道具(而不是组件道具),并在其中传递“ / about”作为道具在这个例子中,是Home组件。
在Home内的componentDidMount()或useEffect()挂钩中,执行以下操作:
useEffect() {
//check that this.props.refreshRoute actually exists before executing the
//following line
this.props.history.replace(this.props.refreshRoute);
}
我假设您的Home组件正在渲染类似的内容:
<Router>
<Route exact path="/" component={SomeComponent} />
<Route path="/about" component={AboutComponent} />
</Router>
向https://tylermcginnis.com/react-router-pass-props-to-components/致谢,以了解如何将道具传递到路线中的组件。
答案 40 :(得分:0)
如果您来这里是在使用apache并且没有.htaccess文件,那么这是一个对我有用的配置文件:
sites-enabled/somedomain.com.conf
<VirtualHost *:80>
ServerName somedomain.com
ServerAlias *.somedomain.com
DocumentRoot /www/somedomain.com/build
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /www/somedomain.com/build/index.html [L,NC,QSA]
</VirtualHost>
答案 41 :(得分:0)
假设您具有以下本地路由定义
<Route exact path="/" render={routeProps => (
<Home routeProps={routeProps}/>
)}/>
{/*optional catch-all router */}
<Route render={routeProps => (
<div><h4>404 not found</h4></div>
)}/>
在您的Home组件上,您可以在ComponentWillMount事件中拦截请求,
const searchPath = this.props.routeProps.location.search;
if (searchPath){
this.props.routeProps.history.push("/" + searchPath.replace("?",""));
}
else{
/*.... originally Home event */
}
现在,您可以请求/?joblist,而不是在url上调用/ joblist,组件将自动将请求重定向到/ joblist(请注意路径中的额外问号)
答案 42 :(得分:0)
我正在使用WebPack,遇到同样的问题解决方案=> 在您的server.js文件中
const express = require('express');
const app = express();
app.use(express.static(path.resolve(__dirname, '../dist')));
app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, '../dist/index.html'));
// res.end();
});
答案 43 :(得分:0)
带有示例的完整路由器(React Router v4):
示例工作示例检出以下项目。
https://github.com/eh3rrera/react-router-4-example
下载后
1.)在cmd中使用“ npm install”安装项目
2.)“ npm start”启动您的React应用
注意:您需要Node js软件才能在Windows中运行。 Mac OS具有默认节点。
欢呼
答案 44 :(得分:0)
修复刷新或直接调用URL时出现的“无法获取/ URL”错误。
配置您的 webpack.config.js ,以期望给定链接具有这种路由。
module.exports = {
entry: './app/index.js',
output: {
path: path.join(__dirname, '/bundle'),
filename: 'index_bundle.js',
publicPath: '/'
},
答案 45 :(得分:0)
我喜欢这种处理方式。尝试添加: 在服务器端 yourSPAPageRoute / * 可以解决此问题。
之所以采用这种方法,是因为就算是原生HTML5历史记录API也不支持页面刷新时进行正确的重定向(据我所知)。
注意:选定的答案已经解决了这个问题,但我正在尝试更具体。
希望有帮助。
答案 46 :(得分:0)
我遇到了同样的问题,this解决方案对我们有用..
背景:
我们在同一台服务器上托管多个应用。当我们刷新服务器时,不会理解在该特定应用程序的dist文件夹中查找索引的位置。以上链接将带您了解对我们有用的东西...希望这有所帮助,因为我们花了相当长的时间来找出满足我们需求的解决方案。
我们正在使用:
package.json
"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}
我的webpack.config.js
webpack.config.js
/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: __dirname + '/app/views/index.html',
filename: 'index.html',
inject: 'body'
});
module.exports = {
entry: [
'babel-polyfill', './app/index.js'
],
output: {
path: __dirname + '/dist/your_app_name_here',
filename: 'index_bundle.js'
},
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
query : {
presets : ["env", "react", "stage-1"]
},
exclude: /node_modules/
}]
},
plugins: [HTMLWebpackPluginConfig]
}
我的index.js
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'
const store = configureStore();
const browserHistory = useRouterHistory(createHistory) ({
basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)
persistStore(store, {blacklist: ['routing']}, () => {
console.log('rehydration complete')
})
// persistStore(store).purge()
ReactDOM.render(
<Provider store={store}>
<div>
<Routes history={history} />
</div>
</Provider>,
document.getElementById('mount')
)
我的app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.get('/*', function (req, res) {
res.render('index');
});
app.listen(8081, function () {
console.log('MD listening on port 8081!');
});
答案 47 :(得分:0)
使用preact-router
进行Preact的解决方案适用于刷新和直接访问
对于那些通过Google发现这一点的人来说,这里是preact-router + hash历史的演示:
const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
<div>
<AddressBar />
<Router history={createHashHistory()}>
<div path="/">
<p>
all paths in preact-router are still /normal/urls.
using hash history rewrites them to /#/hash/urls
</p>
Example: <a href="/page2">page 2</a>
</div>
<div path="/page2">
<p>Page Two</p>
<a href="/">back to home</a><br/>
</div>
</Router>
</div>
);
答案 48 :(得分:0)
对于那些使用IIS 10的人来说,这就是你应该做的事情。请确保您使用的是browserHistory。至于参考,我将给出路由的代码,但这不重要,重要的是下面的组件代码之后的下一步:
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<div>
<Root>
<Switch>
<Route exact path={"/"} component={Home} />
<Route path={"/home"} component={Home} />
<Route path={"/createnewproject"} component={CreateNewProject} />
<Route path={"/projects"} component={Projects} />
<Route path="*" component={NotFoundRoute} />
</Switch>
</Root>
</div>
</Router>
)
}
}
render (<App />, window.document.getElementById("app"));
由于问题是IIS从客户端浏览器接收请求,它会将URL解释为要求页面,然后返回404页面,因为没有可用页面。执行以下操作:
答案 49 :(得分:-1)
当你得到刷新dom组件后无法获得403错误时非常简单。只需在您的web pack配置中添加这一行,'historyApiFallback:true'。这节省了我一整天。