Home > database >  React BrowserRouter works when navigating on localhost. Refreshing a not-home-page when deployed thr
React BrowserRouter works when navigating on localhost. Refreshing a not-home-page when deployed thr

Time:12-29

My code is using React-router-dom. It works on gh-pages with all navigation within the page. However, accessing by adding /blog to the url or refreshing the /blog page returns 404 not found. The app is structured like this:

App.js

function App() {
  return (
    <div className="App" >
      <header className="App-header" width="100%" >
          <BrowserRouter basename="/">
            <Switch>
            <Route component={Main} exact path="/" /> 
            <Route component={Blog} exact path="/blog" /> 
            </Switch>
          </BrowserRouter>
      </header>
    </div>
  );
}
export default App;

Blog.js:

function Blog() {
  return (
    <div className="App" >
      <header className="App-header" width="100%" >
        <div id="home" width="100%">
          <BrowserRouter id="blog">
              
              <div>
                <Route component={AllPosts} exact path="/blog/"  />
                <Route component={OnePost} exact path="/blog/:slug" />
              </div>
              
          </BrowserRouter>

          <SidebarIfBrowser />

        </div>
      </header>
    </div>
  );
}

export default Blog;

Do I miss something essential?

CodePudding user response:

The issue looks to be about how you are using nested routes.

First in App.js remove the exact because you don't want it to be exact

// App.js
<Switch>
    <Route component={Main} exact path="/" /> 
    <Route component={Blog} path="/blog" /> 
</Switch>

Now in your Blog.js there are a few edits you need to make. First is to replace your BrowserRouter with Switch. You only want to have 1 BrowserRouter in your entire app and it should be in the high level which is what you have in your App.js.
Then you want to change the paths in your Routes. You dont need to include /blog/ in them since they are nested routes within the /blog route from your App.js Technically what you have before would of been /blog/blog

// Blog.js
function Blog() {
  return (
    <div className="App" >
      <header className="App-header" width="100%" >
        <div id="home" width="100%">
          <Switch>
              <div>
                <Route component={AllPosts} exact path="/"  />
                <Route component={OnePost} exact path="/:slug" />
              </div>
          </Switch>

          <SidebarIfBrowser />

        </div>
      </header>
    </div>
  );
}

export default Blog;

note this only works for react-router v5 and if you are using v6 then there are some other changes you would need

CodePudding user response:

This happens because you're making a GET request on the server for a non existing route. You can fix this by following the steps bellow:

1. Point the home page in your package.json

 {
    ...
    "homepage": ".",
    ...
}

2. Create a .htaccess file and place it in the root directory of your app

RewriteEngine On
            RewriteCond %{HTTP_HOST} ^www\.
            RewriteRule ^(.*)$ https://yourdomain.com/$1 [R=301,L]
        
            #RewriteCond %{THE_REQUEST} ^GET.*index\.html [NC]
            #RewriteRule (.*?)index\.html/*(.*) /$1$2 [R=301,NE,L]
        
        
         RewriteEngine On
            RewriteCond %{HTTPS} off
            RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

NOTE: This is valid only when you deploy your React app. On development you can access any route by only using React Router.

CodePudding user response:

This is a well known problem when deploying a SPA to github pages. To make the client side routing work, every request must be redirected to the index.html and this behavior is not implemented by github pages.

This is explained in the create react app. It seems that you have two solutions :

  1. switch from using HTML5 history API to routing with hashes
  2. follow this guide. You must add a custom 404.html page to your project and add a custom script tag to your index.html page. I already used this solution, it worked well for me.
  • Related