React-router v4-can not GET * url *

我开始使用反应路由器 v4。我在 app.js 中有一个简单的 <Router>和一些导航链接(见下面的代码)。如果我导航到 localhost/vocabulary,路由器会将我重定向到右边的页面。然而,当我按下重载(F5)后(localhost/vocabulary) ,所有的内容消失和浏览器报告 Cannot GET /vocabulary。这怎么可能?有人能给我解决这个问题的线索吗(正确地重新加载页面) ?

App.js:

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import { Switch, Redirect } from 'react-router'
import Login from './pages/Login'
import Vocabulary from './pages/Vocabulary'


const appContainer = document.getElementById('app')


ReactDOM.render(
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/vocabulary">Vocabulary</Link></li>
</ul>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/vocabulary" component={Vocabulary} />
</Switch>
</div>
</Router>,
appContainer)
70931 次浏览

I'm assuming you're using Webpack. If so, adding a few things to your webpack config should solve the issue. Specifically, output.publicPath = '/' and devServer.historyApiFallback = true. Here's an example webpack config below which uses both of ^ and fixes the refresh issue for me. If you're curious "why", this will help.

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');


module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}
]
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};

I wrote more about this here - Fixing the "cannot GET /URL" error on refresh with React Router (or how client side routers work)

Just to supplement Tyler's answer for anyone still struggling with this:

Adding the devServer.historyApiFallback: true to my webpack config (without setting publicPath) fixed the 404/Cannot-GET errors I was seeing on refresh/back/forward, but only for a single level of nested route. In other words, "/" and "/topics" started working fine but anything beyond that (e.g. "/topics/whatever") still threw a 404 on refresh/etc.

Just came across the accepted answer here: Unexpected token < error in react router component and it provided the last missing piece for me. Adding the leading / to the bundle script src in my index.html has solved the issue completely.

I was having the same issue, what fixed it for me was editing my package.json file, and under scripts: {

"build": "webpack -d && copy src\\index.html dist\\index.html /y && webpack-dev-server --content-base src --inline --port 3000"

at the end of my webpack build code I added --history-api-fallback this also seemed like the easiest solution to the Cannot GET /url error

Note: the next time you build after adding --history-api-fallback you will notice a line in the output that looks like this (with whatever your index file is):

404s will fallback to /index.html

If you use Webpack check your configuration in part of server configuration for the "contentBase" attribute. You can set by this example:

devServer: {
...
contentBase: path.join(__dirname, '../')
...
}

I also had success with this by adding ... historyApiFallback: true

devServer: {
contentBase: path.join(__dirname, "public"),
watchContentBase: true,
publicPath: "/dist/",
historyApiFallback: true
}

If your application is hosted on a static file server, you need to use a instead of a .

import { HashRouter } from 'react-router-dom'


ReactDOM.render((
<HashRouter>
<App />
</HashRouter>
), holder)

https://github.com/ReactTraining/react-router/blob/v4.1.1/FAQ.md#why-doesnt-my-application-render-after-refreshing

If you are using Express (not Webpack), this worked for me..

app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})

It worked for me just need just addding devServer { historyApiFallback: true } is OK, not need use publicPath: '/'

usage like:

  devServer: {
historyApiFallback: true
},

Adding to the accepted answer, if you are using the HtmlWebpackPlugin and still getting errors double check the filename property. If you are setting the filename specifically for production then you will need to add a condition to set the filename contingent on the WEBPACK_DEV_SERVER variable. Please see the example below:

new HtmlWebpackPlugin({
template: './src/index.html',
filename: process.env.WEBPACK_DEV_SERVER ? 'index.html' : PROD_HTML_PATH,
})
If you are using webpack. You need to add


devServer: {
historyApiFallback: true,
}
        

Example ::
        

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
        

module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}
]
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};

Work in React-router v6 with Webpack 5
(https://webpack.js.org/configuration/dev-server/#devservermagichtml):

devServer: {
magicHtml: true,
historyApiFallback: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'),
publicPath: '/',
})
]