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

问题描述 投票:442回答:33

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

例如,我在localhost/joblist,一切都很好,因为我来到这里按一个链接。但如果我刷新网页,我得到:

Cannot GET /joblist

默认情况下,它不像这样工作。最初我的网址为localhost/#/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);
});
javascript url reactjs router react-router
33个回答
825
投票

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

Server-side vs Client-side

要理解这一点的第一件大事是,现在有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正在为您执行路由,但它们在服务器端失败,除非您让服务器了解它们。

Combining server- and client-side routing

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

这就是你的选择开始的地方。解决方案包括完全绕过问题,通过返回引导HTML的全能路由,以及服务器和客户端运行相同JS代码的全面同构方法。

.

完全绕过问题:哈希历史

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

缺点:

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

.

包罗万象

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

缺点:

  • 设置起来比较复杂
  • 仍然没有好的SEO

.

混合动力

在混合方法中,您可以通过为特定路由添加特定脚本来扩展catch-all场景。您可以制作一些简单的PHP脚本来返回包含内容的网站最重要的页面,因此Googlebot至少可以查看您网页上的内容。

缺点:

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

.

同构

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

缺点:

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

.

Which should I use?

选择你可以逃脱的那个。就我个人而言,我觉得这一切都足够简单,所以这将是我的最低限度。此设置允许您随着时间的推移改进。如果您已经使用Node JS作为服务器平台,我肯定会调查做一个同构应用程序。是的,一开始很难,但是一旦掌握了它,它实际上是解决问题的一个非常优雅的解决方案。

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

如果您想了解有关使用React进行同构(也称为“通用”)渲染的更多信息,可以参考以下主题:

另外,为了帮助您入门,我建议您查看一些入门套件。选择一个符合您对技术堆栈的选择(请记住,React只是MVC中的V,您需要更多东西来构建完整的应用程序)。首先看看Facebook本身发布的那个:

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

我从这些开始:

目前我使用的是通用渲染的家庭酿造版本,其灵感来自上面的两个入门套件,但它们现在已经过时了。

祝你好运!


12
投票

这可以解决您的问题

我在生产模式下的ReactJS应用程序中也遇到了同样的问题。这是问题的2解决方案。

1.将路由历史记录更改为“hashHistory”而不是browserHistory

Error Pages 403 Rule

现在使用该命令构建应用程序

 <Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
 </Router>

然后将build文件夹放在var / www /文件夹中,现在应用程序正常工作,在每个url中添加了#tag。喜欢

localhost /#/ home localhost /#/ aboutus

解决方案2:没有使用browserHistory的#tag,

在您的路由器中设置您的历史记录= {browserHistory},现在使用sudo npm run build构建它。

您需要创建“conf”文件来解决404未找到的页面,conf文件应该是这样的。

打开你的终端输入以下命令

cd / etc / apache2 / sites-available ls nano sample.conf在其中添加以下内容。

sudo npm run build

现在,您需要使用以下命令启用sample.conf文件

 <VirtualHost *:80>
    ServerAdmin [email protected]
    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>

然后它会要求你重新加载apache服务器,使用sudo service apache2 reload或restart

然后打开localhost / build文件夹并添加包含以下内容的.htaccess文件。

cd /etc/apache2/sites-available
sudo a2ensite sample.conf

现在应用程序正常运行。

注意:将0.0.0.0 ip更改为本地IP地址。

如果对此有任何疑问,请随时提出评论。

我希望它对其他人有所帮助。


9
投票

生产堆栈:React,React Router v4,BrowswerRouter,Express,Nginx

1)用户浏览器路由器,用于漂亮的网址

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

2)使用// app.js import { BrowserRouter as Router } from 'react-router-dom' const App = () { render() { return ( <Router> // your routes here </Router> ) } } 为所有未知请求添加index.html

/*

3)用// 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) } }) }) 捆绑webpack

4)运行webpack -pnodemon server.js

编辑:你可能想让nginx在服务器块中处理这个并忽略第2步:

node server.js

8
投票

将此添加到webpack.config.js

location / {
    try_files $uri /index.html;
}

6
投票

尝试使用以下代码在公用文件夹中添加“.htaccess”文件。

devServer: {
      historyApiFallback: true
  }

6
投票

如果您使用的是Create React App:

对于许多主要托管平台的解决方案,您可以在Create React App页面上找到RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d RewriteRule ^ - [L] RewriteRule ^ /index.html [L] 。例如,我使用React Router v4和Netlify作为我的前端代码。所需要的只是将1个文件添加到我的公共文件夹(“_redirects”)和该文件中的一行代码:

HERE

现在我的网站在进入浏览器或有人点击刷新时正确呈现了像mysite.com/pricing这样的路径。


3
投票

这个主题有点陈旧和解决但我想建议你一个简单,明确和更好的解决方案。如果您使用Web服务器,它可以工作。

在http 404的情况下,每个Web服务器都能够将用户重定向到错误页面。要解决此问题,您需要将用户重定向到索引页面。

如果您使用Java基本服务器(tomcat或任何Java应用程序服务器),解决方案可能如下:

veb.hml:

/*  /index.html  200

例:

  • GET <?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>
  • Web服务器抛出http 404,因为服务器端不存在此页面
  • 错误页面配置告诉服务器将index.jsp页面发送回用户
  • 那么JS将在客户端完成剩下的工作,因为客户端的url仍然是qazxsw poi。

就是这样,没有更多魔法需要:)


3
投票

如果您在IIS上托管您的react应用程序,只需添加一个包含以下内容的web.config文件:

http://example.com/about

这将告诉IIS服务器将主页面返回到客户端而不是404错误,并且不需要使用哈希历史记录。


2
投票

如果确实有index.html的回退,请确保在index.html文件中有以下内容:

http://example.com/about

这可能因项目而异。


2
投票

我还没有使用服务器端渲染但是我遇到了与OP相同的问题,其中Link似乎大部分时间工作正常,但是当我有一个参数时失败了。我会在这里记录我的解决方案,看看它是否有助于任何人。

我的主要jsx包含这个:

<?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>

这适用于第一个匹配的链接,但是当嵌套在该模型的详细信息页面上的<script> System.config({ baseURL: '/' }); </script> 表达式中的:id更改时,URL会在浏览器栏中更改,但页面的内容最初不会更改以反映链接的模型。

麻烦的是我用<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} /> <Link>设置模型。组件刚刚安装一次,这意味着第一个模型是粘在页面上的模型,随后的链接会更改道具,但页面看起来保持不变。

props.params.idcomponentDidMount(它基于下一个道具)中的组件状态中设置模型可以解决问题,并且页面内容会发生变化以反映所需的模型。


2
投票

如果你正在使用firebase,你所要做的就是确保你的应用程序根目录中的firebase.json文件中有一个重写属性(在托管部分)。

例如:

componentDidMount

希望这可以节省别人的挫折和浪费时间。

快乐的编码......

进一步阅读该主题:

componentWillReceiveProps

{ "hosting": { "rewrites": [{ "source":"**", "destination": "/index.html" }] } }


95
投票

这里的答案都非常有用,对我来说有用的是配置我的Webpack服务器以期望路由。

  devServer: {
    historyApiFallback: true,
    contentBase: './',
    hot: true
  },

historyApiFallback是我解决这个问题的原因。现在路由工作正常,我可以刷新页面或直接输入URL。无需担心节点服务器上的解决方法。这个答案显然只有在你使用webpack时才有效。

编辑:在这里查看我的答案,了解为什么这是必要的更详细的原因:https://stackoverflow.com/a/37622953/5217568


2
投票

我找到了带反应路由器(Apache)的SPA的解决方案。只需添加.htaccess即可

https://firebase.google.com/docs/hosting/full-config#rewrites

来源:Firebase CLI: "Configure as a single-page app (rewrite all urls to /index.html)"


1
投票

如果您在IIS中托管;将此添加到我的webconfig解决了我的问题

<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>

您可以为任何其他服务器进行类似的配置


1
投票

如果有人在这里寻找与Laravel的React JS SPA的解决方案。接受的答案是对这些问题发生原因的最佳解释。如前所述,您必须配置客户端和服务器端。在您的刀片模板中,包含js捆绑文件,请确保像这样使用https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

    <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
        <remove statusCode="500" subStatusCode="100" />
        <remove statusCode="500" subStatusCode="-1" />
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
        <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
        <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
    </httpErrors>

在路由中,请确保将其添加到刀片模板所在的主端点。例如,

URL facade

以上是刀片模板的主要端点。现在添加一个可选路线,

<script src="{{ URL::to('js/user/spa.js') }}"></script>

发生的问题是首先加载刀片模板,然后加载反应路由器。所以,当你加载Route::get('/setting-alerts', function () { return view('user.set-alerts'); }); 时,它会加载html和js。但是当你加载Route::get('/setting-alerts/{spa?}', function () { return view('user.set-alerts'); }); 时,它首先在服务器端加载。由于在服务器端,此位置没有任何内容,因此返回未找到。如果你有这个可选的路由器,它会加载同一个页面并且反应路由器也被加载,然后反应加载器决定显示哪个组件。希望这可以帮助。


1
投票

如果您在后端使用Express或其他一些框架,您可以添加如下的类似配置并查看配置中的Webpack公共路径,如果您使用的是BrowserRouter,它甚至可以在重新加载时正常工作

'/setting-alerts'

1
投票

当我使用.Net Core MVC这样的东西帮助我:

'/setting-alerts/about'

基本上在MVC方面,所有不匹配的路线都将落入` expressApp.get('/*', (request, response) => { response.sendFile(path.join(__dirname, '../public/index.html')); });` 中指定的 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"); } } 。在Home/Index内部,可以获取原始请求URL并在需要的地方传递它。

startup.cs

startup.cs

0
投票

我有同样的问题,Index解决方案为我们工作..

背景:

我们在同一台服务器上托管多个应用。当我们刷新服务器时,不会理解在该特定应用程序的dist文件夹中查找索引的位置。以上链接将带您了解对我们有用的东西...希望这有所帮助,因为我们花了相当长的时间来找出满足我们需求的解决方案。

我们正在使用:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });

我的webpack.config.js

this

我的index.js

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"
}

我的app.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]
}

0
投票

使用react-router进行Preact的解决方案

适用于刷新和直接访问

对于那些通过谷歌发现这一点的人来说,这是一个preact-router + hash历史的演示:

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')
)

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


0
投票

对于那些使用IIS 10的人来说,这是你应该做的事情。请确保您使用的是browserHistory。至于参考,我将给出路由的代码,但这不重要,重要的是下面的组件代码之后的下一步:

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

由于问题是IIS从客户端浏览器接收请求,它会将URL解释为要求页面,然后返回404页面,因为没有可用页面。请执行下列操作:

  1. 打开IIS
  2. 展开服务器,然后打开站点文件夹
  3. 单击网站/应用程序
  4. 转到错误页面
  5. 在列表中打开404错误状态项
  6. 而不是“将内容从静态文件插入错误响应”选项,将其更改为“在此站点上执行URL”并将“/”斜杠值添加到URL。

它现在可以正常工作了。

https://jsfiddle.net/developit/gLyL6rbn/ 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"));

我希望它有所帮助。 :-)


0
投票

我喜欢这种处理方式。尝试在服务器端添加:yourSPAPageRoute / *以解决此问题。

我采用这种方法,因为即使是原生的HTML5 History API也不支持页面刷新时的正确重定向(据我所知)。

注意:已选择的答案已经解决了这个问题,但我正在尝试更具体。

enter image description here

enter image description here经过测试,只是想分享一下。

希望能帮助到你。


0
投票

修复刷新或直接调用URL时出现“无法GET / URL”错误。

配置你的webpack.config.js以期望给定的链接像这样的路由。

Express Route

45
投票

对于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


0
投票

我正在使用WebPack,我有同样的问题Solution =>在你的server.js文件中

Test - History API

module.exports = { entry: './app/index.js', output: { path: path.join(__dirname, '/bundle'), filename: 'index_bundle.js', publicPath: '/' },


43
投票

你可以改变你的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"


27
投票

可以通过两种不同的方式调用路由器,具体取决于导航是在客户端还是在服务器上进行。您已将其配置为客户端操作。关键参数是run method的第二个位置。

当您使用React Router Link组件时,它会阻止浏览器导航并调用transitionTo来执行客户端导航。您正在使用HistoryLocation,因此它使用HTML5历史记录API通过模拟地址栏中的新URL来完成导航错觉。如果您使用的是较旧的浏览器,则无法使用。您需要使用HashLocation组件。

当您点击刷新时,您将绕过所有React和React路由器代码。服务器获取/joblist的请求,它必须返回一些东西。在服务器上,您需要将请求的路径传递给run方法,以便呈现正确的视图。您可以使用相同的路线图,但您可能需要对Router.run进行不同的调用。正如Charles指出的那样,您可以使用URL重写来处理这个问题。另一种选择是使用node.js服务器来处理所有请求,并将路径值作为location参数传递。

例如,在express中,它可能如下所示:

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。


20
投票

在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是重要的组成部分


15
投票

我使用create-react-app来制作一个网站,并且在这里提出了相同的问题。我使用BrowserRouting包中的react-router-dom。我在Nginx服务器上运行,为我解决的是将以下内容添加到/etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

这对应于在运行Apache时将以下内容添加到qazxsw poi中

.htaccess

这似乎也是Facebook自己提出的解决方案,可以找到Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.html [QSA,L]


14
投票

Webpack Dev Server有一个选项来启用它。打开here并添加package.json。这个解决方案对我有用。

--history-api-fallback


13
投票

如果您通过AWS Static S3 Hosting和CloudFront托管react应用程序

这个问题由CloudFront以403 Access Denied消息响应,因为它预期/某些/其他/路径存在于我的S3文件夹中,但该路径仅存在于React与react-router的路由中。

解决方案是设置分发错误页面规则。转到CloudFront设置并选择您的分发。接下来转到“错误页面”选项卡。单击“创建自定义错误响应”并为403添加条目,因为这是我们获得的错误状态代码。将响应页面路径设置为/index.html,将状态代码设置为200.最终结果令我惊讶于它的简单性。提供了索引页面,但URL保留在浏览器中,因此一旦反应应用程序加载,它就会检测URL路径并导航到所需的路径。

https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls#configuring-your-server

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.