手动刷新或编写时,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);
});
神无Green前端2020/03/09 22:48:05

Joshua Dyck的答案中添加更多信息

如果您使用的是Firebase,并且要同时使用根路由和子目录路由,则需要在:中添加以下代码firebase.json

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

例:

您正在为客户建立一个网站。您希望网站的所有者在https://your.domain.com/management中添加信息,同时网站的用户将导航到https://your.domain.com

在这种情况下,您的firebase.json文件将如下所示:

{
  "hosting": {
    "rewrites": [
      {
        "source": "*",
        "destination": "/index.html"
      },
      {
        "source": "/management/**",
        "destination": "/management/index.html"
      }
    ]
  }
}
达蒙小胖2020/03/09 22:48:05

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

我之所以采用这种方法,是因为即使本地HTML5历史记录API也不支持页面刷新时进行正确的重定向(据我所知)。

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

快速路线

测试-历史记录API 经过测试,只想分享。

希望能帮助到你。

Tony达蒙2020/03/09 22:48:05

For those who are using IIS 10, this is what you should do to make this right. Be sure that you are using browserHistory with this. As for reference I will give the code for the routing, but this is not what matters, what matters is the next step after the component code below:

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

Since the problem is IIS receives request from client browsers, it will interpret the URL as if it is asking for a page, then returns a 404 page since there is no available page. Do the following:

  1. Open IIS
  2. Expand Server then open the Sites Folder
  3. Click the website/application
  4. Go to the Error Pages
  5. Open the 404 error status item in the list
  6. Instead of the option "Insert content from static file into the error response", change it to "Execute a URL on this site" and add "/" slash value to the URL.

And it will now work fine.

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

I hope it helps. :-)

SamJim2020/03/09 22:48:05

当我使用.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/03/09 22:48:05

假设您具有以下本地路由定义

<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(请注意路径中的额外问号)

小哥达蒙2020/03/09 22:48:05

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

如果您在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>

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

A十三2020/03/09 22:48:05

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

例如:

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

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

祝您编程愉快...

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

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

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

A小卤蛋Pro2020/03/09 22:48:05

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

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

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

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

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

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

猪猪路易2020/03/09 22:48:05

我找到了带有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/03/09 22:48:05

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

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

这可能因项目而异。

达蒙阿飞斯丁2020/03/09 22:48:05

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

Jim小哥GO2020/03/09 22:48:05

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

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

RewriteRule ^ /index.html [L]  
米亚JinJin樱2020/03/09 22:48:05

如果您使用的是Create React App:

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

/*  /index.html  200

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

Tony阳光2020/03/09 22:48:05

将此添加到 webpack.congif.js

devServer: {
    historyApiFallback: true
}
Mandy逆天2020/03/09 22:48:05

如果您通过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规则

ProTom2020/03/09 22:48:05

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

反应路由器教程

十三蛋蛋2020/03/09 22:48:05

这样可以解决你的问题

在生产模式下的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 reload或重新启动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地址。

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

希望对其他人有帮助。

TonyPro2020/03/09 22:48:05

我刚才使用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/03/09 22:48:04

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

Itachi小哥2020/03/09 22:48:04

您可以更改.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" 此方法是万能的,并且可能是入门的最简单方法。