Reputation: 3293
I have a react app created with create-react-app and am using react-router-dom for routing.
The general layout is:
App.js
<BrowserRouter>
<BodyContent />
</BrowserRouter>
Bodycontent.js
<Fragment>
<Navigation/>
<main>
<ScrollToTopRoute path="/" exact component={HomePage}/>
<ScrollToTopRoute path="/page1" exact component={Page1}/>
<ScrollToTopRoute path="/page1/page2" exact component={Page2}/>
<ScrollToTopRoute path="/page3" exact component={Page3}/>
... etc...
</main>
</Fragment>
The ScrollToTopRoute is simply an extension of the standard router functionality that ensures new pages scroll back to the top for a good UX.
ScrollToTop.js
import React, { Component } from 'react';
import { Route, withRouter } from 'react-router-dom';
import ReactGA from 'react-ga';
ReactGA.initialize('UA-5477132-2');
class ScrollToTopRoute extends Component {
componentDidUpdate(prevProps) {
if (this.props.path === this.props.location.pathname && this.props.location.pathname !== prevProps.location.pathname) {
window.scrollTo(0, 0);
ReactGA.pageview(window.location.pathname + window.location.search);
console.log("Triggered");
}
}
render() {
const { component: Component, ...rest } = this.props;
return <Route {...rest} render={props => (<Component {...props} />)} />;
}
}
export default withRouter(ScrollToTopRoute);
In development the app works as expected, all routes work and if you go directly to a URL like localhost:3000/page1
it will load correctly. I have built the site using yarn build and deployed to a typical VPS. The website and internal links to components/routes all work as expected, however when accessing a URL directly as above such as www.theurl.com/page1
it will 404 and I am at a loss as to why the outcome is different.
Upvotes: 5
Views: 10825
Reputation: 31
Hi react serve single page application so I don't think there is any way you can access your files directly if you are going to use a single react project and a single server ,
I would suggest you using react-router-dom and replacing the href
tags with navigate()
function and a tag with Link
tag , if you want to hide your data then you have to actually make a separate react project or a public folder in your server , basically do ssr for that purpose .
Here is my sample code where I wanted to navigate to my admin panel
const navigate = useNavigate();
if (response.data.success) {
localStorage.setItem('token', JSON.stringify(response.data.token));
// window.location.href = '/admin'//don't use this
navigate('/admin') //use this way
}
Upvotes: 0
Reputation: 21
The equivalent solution for Nginx is:
location / {
# other config here
try_files $uri $uri/ /index.html =404;
}
Upvotes: 2
Reputation: 5700
If you created an app using create-react-app you can use this solution. Create a file called "_redirects" (Note: file name is just _redirects without any extension) in your build folder. Then write the below content in that file:
/* /index.html 200
Reupload your build folder again, and this issue should be fixed now.
Upvotes: 0
Reputation: 325
I was also facing the same issue. fixed it by adding a htaccess file with following content:
<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>
found the solution at: How to fix "404" error when directly accessing a component in react
Upvotes: 3
Reputation: 2587
I believe the underlying reason for this is actually due to how your server is configured.
React Router
can only handle routing after your front-end scripts have been loaded (from the index page), which isn't the case when a user hits the /foo
deeplink route in production.
You'll have to set your server up to return the index page on every route request except for api routes that need to be handled by the server.
This should set your server up to let React Router handle deeplink requests.
If you're using Node and Express it should look something like this:
app.get('*', function (req, res) {
res.send('public/index.html')
})
Let me know if I can explain further.
Upvotes: 5