React-router v4 - cannot GET *url*
I started to use react-router v4. I have a simple <Router>
in my app.js with some navigation links (see code below). If I navigate to localhost/vocabulary
, router redirects me to the right page. However, when I press reload (F5) afterwards (localhost/vocabulary
), all content disappear and browser report Cannot GET /vocabulary
. How is that possible? Can somebody gives me any clue how to solve that (reload the page correctly)?
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)
Solution 1:
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)
Solution 2:
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.