'React-Router v6 not rendering in production
I have run out of wisdom on this issue and hope for any ideas that could bring me on the right track.
I have implemented a React.js SPA that uses react-router-dom
v6 to navigate through the app functions. The App works flawlessly on my localhost. When deployed to production the <Route ... />
renders nothing.
I have checked that the deployment path is correct by rendering an <h2>
element outside the <Routes> ... </Routes>
.
App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const App = () => {
const title = `${(process.env.REACT_APP_TITLE)}`;
const TwentyfourStats = () => (<h2>Works</h2>);
return (
<Router>
<div id="app" className="App">
<h2>{title}</h2>
<div>
<Routes>
<Route path="/" element={<TwentyfourStats />} />
</Routes>
</div>
</div>
</Router>
);
}
export default App;
I have tried setting <Routes homebase={}>
while adjusting "homepage": "..."
in package.json but it made no difference.
Many thanks
UPDATE: I have inlined the component <TwentyfourStats />
in the example to remove any deps on folder structure. The result is the same.
UPDATE 2: The problem is solved, as pointed by @VitaliyRayets by using HashRouter
instead of BrowserRouter
(see answer).
Solution 1:[1]
You use BrowserRouter
that uses the HTML5 history API. Then you visit Home page. It doesn't work because in production the server looks for the file /
, which literally doesn't exist. To fix this issue, the server needs to be configured such that requests to any route would be served the index.html
file in your production build. If you use express.js
it can be done as follows.
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
If you use Nginx
. Config:
location / {
try_files $uri $uri/ /index.html;
}
Apache
:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
Instead of mod_rewrite
, you could also use FallbackResource.
If you haven't access to server you can use HashRouter
that uses the hash portion of the URL (i.e. window.location.hash
) to keep your UI in sync with the URL.
Solution 2:[2]
In my react case this error happened only when I navigate to links with more than one slash: E.g www.abc.com/Users works with apache rewriterule but www.abc.com/Users/[email protected] fails
My solution was to open index.html and make all links point back to main domain.
E.g Replace <link rel="manifest" href="./manifest.json"/>
with <link rel="manifest" href="/manifest.json"/>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Christopher Uduekwe |