James
James

Reputation: 3293

react-router-dom Build Giving 404 When Accessing URL Directly, But Not In Development

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

Answers (5)

Sachin Barpanda
Sachin Barpanda

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

Kenneth Washburn
Kenneth Washburn

Reputation: 21

The equivalent solution for Nginx is:

    location / {
        # other config here
        try_files $uri $uri/ /index.html =404;
    }

Upvotes: 2

Kishan Bharda
Kishan Bharda

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

syd
syd

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

Michael Abeln
Michael Abeln

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

Related Questions