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

我正在使用React-router,当我单击链接按钮时,它可以正常工作,但是当我刷新网页时,它不会加载我想要的内容。

例如,我进去了localhost/joblist,一切都很好,因为我按链接到达这里。但是,如果刷新网页,则会得到:

Cannot GET /joblist

默认情况下,它不是这样工作的。最初,我的URL为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);
});
JinJin2020/05/25 12:06:22

使用ReduxHashRouter对我有用,只需替换:

import {
  Router //replace Router
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <Router history={history}> //replace here saying Router
            <Layout/>
        </Router>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

至:

import {
  HashRouter //replaced with HashRouter
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <HashRouter history={history}> //replaced with HashRouter
            <Layout/>
        </HashRouter>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();
飞羽2020/05/25 12:06:22

对于使用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页面。请执行下列操作:

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

现在它将正常工作。

在此处输入图片说明 在此处输入图片说明

希望对您有所帮助。:-)

西门2020/05/25 12:06:22

当我使用.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" });
        });
凯西里2020/05/25 12:06:22

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

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

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

别太浪2020/05/25 12:06:21

这个主题有点老了,已经解决了,但是我想向您推荐一个简单,清晰和更好的解决方案。如果您使用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>

例:

  • GET http://example.com/about
  • Web服务器抛出http 404,因为此页面在服务器端不存在
  • 错误页面配置告诉服务器将index.jsp页面发送回用户
  • 那么JS将在客户端上完成剩下的工作,因为客户端的网址仍然是http://example.com/about

就是这样,不再需要魔术:)

老丝阿飞2020/05/25 12:06:21

我还没有使用服务器端渲染,但是遇到了与OP相同的问题,在大多数情况下,Link似乎可以正常工作,但是当我有参数时失败了。我将在此处记录我的解决方案,以查看它是否对任何人都有帮助。

我的主要jsx包含以下内容:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

这对于第一个匹配的链接来说效果很好,但是当:id更改<Link>嵌套在该模型的详细信息页面上的表达式时,浏览器栏中的url会更改,但是页面的内容最初并未更改以反映链接的模型。

麻烦的是我曾用来props.params.id设置模型componentDidMount该组件仅安装一次,因此这意味着第一个模型是粘贴在页面上的模型,随后的Links更改了道具,但页面看起来没有变化。

将模型同时设置为组件状态componentDidMountcomponentWillReceiveProps基于组件的状态(此处基于下一个道具)将解决该问题,并且页面内容会更改以反映所需的模型。

伊芙妮2020/05/25 12:06:21

我找到了带有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

别太浪2020/05/25 12:06:21

如果您使用的是Firebase,则只需确保在应用程序根目录(在托管部分中)的firebase.json文件中具有rewrites属性。

例如:

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

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

祝您编程愉快!

关于该主题的进一步阅读:

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

Firebase CLI:“配置为单页应用程序(将所有URL重写为/index.html)”

Mandy村村2020/05/25 12:06:21

如果您使用的是Create React App:

有一个伟大的步行路程,虽然这个问题与许多大型主机平台的解决方案,你可以找到这里的创建做出反应应用页面上。例如,我将React Router v4和Netlify用作前端代码。只需要在我的公用文件夹中添加一个文件(“ _redirects”),然后在该文件中添加一行代码即可:

/*  /index.html  200

现在,当输入浏览器或有人刷新时,我的网站可以正确呈现诸如mysite.com/pricing之类的路径。

宝儿2020/05/25 12:06:21

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

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  
千羽2020/05/25 12:06:21

如果确实有index.html的备用版本,请确保在index.html文件中具有以下内容:

<script>
  System.config({ baseURL: '/' });
</script>

这可能因项目而异。

镜风2020/05/25 12:06:21

如果您在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错误,并且不需要使用哈希历史记录。

凯西里2020/05/25 12:06:21

Webpack Dev Server具有启用此功能的选项。打开package.json并添加--history-api-fallback该解决方案为我工作。

反应路由器教程

伊芙妮2020/05/25 12:06:21

将此添加到webpack.config.js

devServer: {
    historyApiFallback: true
}
MonsterKK2020/05/25 12:06:20

这样可以解决你的问题

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

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

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

现在使用命令构建应用

sudo npm run build

然后将build文件夹放在您的var / www /文件夹中,现在该应用程序可以正常工作,在每个URL中添加#标签。喜欢

本地主机/#/ home本地主机/#/ aboutus

解决方案2:不使用浏览器历史记录#标签,

在路由器中设置您的历史= {browserHistory},现在使用sudo npm run build对其进行构建。

您需要创建“ conf”文件来解决“ 404找不到页面”,conf文件应如下所示。

打开您的终端,键入以下命令

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

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

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

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

然后它将要求您使用sudo服务apache2重新加载或重新启动apache服务器

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

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

现在,该应用程序可以正常运行。

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

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

希望对其他人有帮助。

千羽2020/05/25 12:06:20

如果您通过AWS Static S3 Hosting和CloudFront托管React应用

CloudFront响应403 Access Denied消息后就出现了此问题,因为它希望/ some / other / path存在于我的S3文件夹中,但该路径仅存在于React的使用react-router的路由内部。

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

错误页面403规则

镜风2020/05/25 12:06:20

我刚才使用create-react-app制作了一个网站,并在此处遇到了同样的问题。BrowserRoutingreact-router-dom包装中使用我在Nginx服务器上运行,对我来说解决了什么是将以下内容添加到/etc/nginx/yourconfig.conf

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

这对应于.htaccess在运行Appache的情况下将以下内容添加到

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

这似乎也是Facebook自己建议的解决方案,可以在这里找到

王者一打九达蒙2020/05/25 12:06:20

在index.html中head,添加以下内容:

<base href="/">
<!-- This must come before the css and javascripts -->

然后,当与webpack dev服务器一起运行时,请使用此命令。

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback 是重要的部分

阿飞2020/05/25 12:06:20

您可以更改.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>

我正在使用react: "^16.12.0"并且react-router: "^5.1.2" 这种方法是万能的,可能是入门的最简单方法。