404 when trying to enter a react app route
Asked Answered
C

3

6

I just deployed my react app build on c-panel. The app includes different routes and everytime I try to get to one of them I get 404 Not found. For example if I try to get to http://example.com/ it will enter the website, and if I'll press on a button which links me tohttp://example.com/articles it will work. But If I'll try to get http://example.com/articles from a link that I shared or just typing this address I'll get 404 Not found. This is not happening when I'm running the develope mode on localhost.

I changed the homepage url - "homepage": "http://example.com", in package.json and it did not effect.

My app root is wrapped with <Router>

function App() {
  return (
    <Provider store={store}>
      <Router>
        <React.Fragment>
          <CssBaseline />
          <Header title="exampletitle" />
          <MobileHeader />
          <Main />
          <BottomNavbar />
        </React.Fragment>
      </Router>
    </Provider>
  );
}

And this is Main.js component which is maneuvered by the routes.

function Main(props) {
  return (
    <div>
      <Switch>
        <Route exact path="/" component={Homepage} />
        <Route exact path="/about" component={About} />
        <Route exact path="/signup" component={Registerpage} />
        <Route exact path="/ap" component={Adminpage} />
        <Route exact path="/signin" component={SignIn} />
        <Route exact path="/userpanel" component={UserPanelPage} />
        <Route path="/article/:category" component={Articlepage} />
        <Route path="/articlepage/:id" component={ReadArticlePage} />
      </Switch>
    </div>
  );
}

Can someone give me a clue how to make those pages load when I enter them directly by their link?

Counterpart answered 27/5, 2020 at 15:55 Comment(3)
You have path="/article/:category" which is the closest to articles. Probably a typo. Or it tries to render the route from the back-end and that's why it is 404.Gibbs
@Gibbs I'm not talking specifically about this route. All the route are doing the same.Counterpart
Probably the back-end tries to look for the route, I have explained a similar scenario in this answer, maybe this helps to understand what is happening.Gibbs
F
8

If your application is working for all the routes when you navigate using <Link> and history.push but throwing 404 Not Found when you type a URL other than http://example.com, say http://example.com/articles, directly in your browser, you need to:

Teach your server to handle 404s by redirecting to the index.html page.

You can do this in one of the following ways:

  1. Add a custom 404 page which redirects you to index.html.
  2. If your hosting solution, c-panel, provides an error page setting for the deployment, provide index.html as the error page.
  3. Use HashRouter from react-router. Check HashRouter Solution and What's HashRouter.

Also, check notes-on-client-side-routing and How to deploy on cPanel.

Fomentation answered 27/5, 2020 at 18:49 Comment(1)
Here is how to do it on nginx and apache2 servers.Fomentation
J
0

I think I am a bit late ,But the best solution is to : Use HashRouter instead of BrowserRouter and also add a 404.html to public folder with this source code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
    name="viewport"
    content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1"/>
    <title>Your Page Title</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script>
    var path = window.location.pathname;
    path = path[0] + "#" + path;
    var url = window.location.protocol + "//" + window.location.hostname + path;
    //document.write("Redirecting To: "+url);
    window.location.href=url;
    </script>
  </body>
</html>

So now, if you visit http://example.com/articles it will automatically redirect to http://example.com/#/articles almost instantly which you won't even notice and render correctly without any 404 error!!!.

Note: This answer is suitable if you are using github, if you are using cpanel use custom 404 page with above source code.

Jost answered 8/1, 2021 at 13:28 Comment(0)
R
0

I was having this problem (using Github Pages instead of Cpanel) and didn't want to use a hash router to avoid having "#" in my URLs. I created a custom 404 page, but didn't want to simply redirect back to my homepage because the whole point was to be able to share specific routes (in my case blog posts).

For my project, any non-homepage route would end with a /slug. So, in my 404, I redirected to the homepage with the URL containing the string after the last "/" as a search parameter:

   <script>
  // Extract possible slug from the attempted URL
  const currentUrl = window.location.href;
  const indexOfLastSlash = currentUrl.lastIndexOf("/");
  const possibleSlug = currentUrl.substr(indexOfLastSlash + 1);

  // Redirect to homepage with possible slug as search parameter
  if (currentUrl) {
    window.location.href = `/yourbasename?redirect=${encodeURIComponent(
      possibleSlug
    )}`;
  } else {
    window.location.href = "/yourbasename";
  }
</script>

You would want to adjust for your situation. Then, in my root component, I check and see if the path contains a search param. If it does, I check if it is a valid slug. If yes, then navigate to the appropriate route, otherwise navigate to an error page. (slugMap is just a map of all my possible slugs I created for fast lookup.)

  import { useEffect } from "react";
  import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
    
  const [searchParams] = useSearchParams();    
  const navigate = useNavigate();
  const location = useLocation();  

  // Get possible slug from search params
  const possibleSlug = searchParams.get("redirect");

  // Navigate appropriately if there are search params from the 404 redirect
  useEffect(() => {
    if (possibleSlug) {
      if (slugMap[possibleSlug]) {            
        navigate(`/posts/${possibleSlug}`);
      } else {            
        navigate(`/notfound/`);
      }
    } else if (searchParams.size > 0) navigate(`/notfound/`);
  }, [searchParams]);
Randell answered 13/7 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.