1

I'm having an issue with my React app that I recently deployed to Banahosting. The app works perfectly in the local environment, and the page is refreshed when I click links inside the webpage; but navigation is broken when building and uploading to the internet with a hosting server. Here's the issue:

When I navigate to the site (https://quierotraspasarlo.com), the main page loads fine, but when I click on a link, the URL changes in the address bar, but the page does not reload to reflect the new route. However, if I manually enter the new URL into the address bar and refresh the page, it loads the correct page.

I am using react-router-dom for routing. Here is how I've set up my main App.js file:

import React, { createContext } from "react";
import { BrowserRouter  as Router } from "react-router-dom";
import "./App.css";
import TopBar from "./components/TopBar";
import MainContent from "./components/MainContent";
import Footer from "./components/Footer";

export const CurrencyContext = createContext();

const App = () => {
  const currency = "€";
  return (
    <CurrencyContext.Provider value={currency}>
      <Router basename={process.env.PUBLIC_URL}>
        <div className="app">
          <TopBar />
          <MainContent />
          <Footer></Footer>
        </div>
      </Router>
    </CurrencyContext.Provider>
  );
};

export default App;

Things I have tried:

I've attempted to use <HashRouter> instead of <BrowserRouter>. This resulted in the URL looking like https://quierotraspasarlo.com/#/city/2, but the problem persisted.

I've included a .htaccess file in the public directory of my app with the following rules:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

I made sure that the Apache mod_rewrite module is enabled on my server.

I've tried setting the homepage field in package.json to the URL of my app ("homepage": "https://quierotraspasarlo.com"). Despite all these efforts, the problem persists. Any advice or guidance on what I may be missing here would be greatly appreciated.

Thank you in advance for your help!

PD: I know the question is a bit specific, because all information is related to my webpage, but this issue can occur to anybody trying to upload their project to "the internet", i.e., using a hosting service to host their webpage (and that its navigation works great in a local environment).

This is the MainContent.js file:

import React, { useState } from "react";
import { Routes, Route } from "react-router-dom";
import CityCarousel from "./CityCarousel";
import WelcomeBanner from "./WelcomeBanner";
import WhyQuieroTraspasarlo from "./WhyQuieroTraspasarlo";
import CityPage from "./CityPage";
import BusinessPage from "./BusinessPage";
import PrivacyPolicy from "./PrivacyPolicy";
import ConditionsOfUse from "./ConditionsOfUse";
import NotFoundPage from "./NotFoundPage";
import AllCitiesPage from "./AllCitiesPage";
import ImInterestedContactForm from "./ImInterestedContactForm";
import BusinessContext from "./BusinessContext";
import IHaveABusinessForm from "./IHaveABusinessForm";
import BusinessAdBanner from "./BusinessAdBanner";
import PopularBusinessesBanner from "./PopularBusinessesBanner";
import HowQuieroTraspasarloWorks from "./HowQuieroTraspasarloWorks";
import "./MainContent.css";

const FullHome = () => {
  return (
    <>
      <WelcomeBanner />
      <div className="break-0x2vw" />
      <CityCarousel />
      <div className="break-0x2vw" />
      <PopularBusinessesBanner />
      <div className="break-0x2vw" />
      <HowQuieroTraspasarloWorks />
      <div className="break-0x2vw" />
      <BusinessAdBanner />
      <div className="break-0x2vw" />

      <WhyQuieroTraspasarlo />
      <div className="break-0x2vw" />
    </>
  );
};

const MainContent = () => {
  const [businessData, setBusinessData] = useState({});

  return (
    <BusinessContext.Provider value={{ businessData, setBusinessData }}>
      <Routes>
        <Route path="/" element={<FullHome />} />
        <Route path="/city/:cityId" element={<CityPage />} />
        <Route
          path="/city/:cityId/business/:businessId"
          element={<BusinessPage setBusinessData={setBusinessData} />}
        />
        <Route path="/contact" element={<ImInterestedContactForm />} />
        <Route path="/all-cities" element={<AllCitiesPage />} />
        <Route path="/privacy-policy" element={<PrivacyPolicy />} />
        <Route path="/conditions-of-use" element={<ConditionsOfUse />} />
        <Route path="/publish-business" element={<IHaveABusinessForm />} />
        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </BusinessContext.Provider>
  );
};

export default MainContent;

joangm_
  • 27
  • 1
  • 12
  • Have you checked this: https://stackoverflow.com/a/58649325/1225070 – Aefits Jul 03 '23 at 12:46
  • The apache rewrite module is used when accepting a new request, which is not the case for you since you are redirecting in your SPA. you can verify this by actually calling the modified url (just enter the addressbar and click enter, then the real page is loaded). Please edit your question by adding MainContent component – tbc Jul 04 '23 at 10:10
  • Good afternoon @tbc, I just added it to the question (I do not know if it is useful or not, but there you have it). Thank you! – joangm_ Jul 05 '23 at 12:25

2 Answers2

0

Since a React App is a SPA, the server knows only one route as there's only one HTML file (index.html). Every time you request the content of a different route, the underlying JavaScript just replaces the content of that single page, while adding a new layer to the browser navigation history.

The only thing you have to do is to tell the server to redirect any request for routes to the home page (/) which is exactly what does this line: RewriteRule . /index.html [L]. I had the same problem with an Apache server (000webhost.com) and I could solve it with the following rules in my .htaccess file.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l (Missing from your config)
  RewriteRule . /index.html [L]
</IfModule>
tem
  • 101
  • 4
  • Thank you for your answer. I tried that and the same is still happening. I recorded a video on what is exactly happening to make it clear: https://drive.google.com/file/d/1Ilayf2ROfM3_88d0M4SiSOcvMNGGIWs1/view?usp=sharing The clickable elements only modify the URL, but do not refresh the page to display the new content. How can I solve it? – joangm_ Jul 04 '23 at 08:28
0

In your code:

import React, { createContext } from "react";
import { BrowserRouter as Router } from "react-router-dom";
import "./App.css";
import TopBar from "./components/TopBar";
import MainContent from "./components/MainContent";
import Footer from "./components/Footer";

export const CurrencyContext = createContext();

const App = () => {
  const currency = "€";
  return (
    <CurrencyContext.Provider value={currency}>
      <Router basename={process.env.PUBLIC_URL}>
        <div className="app">
          <TopBar />
          <MainContent />
          <Footer></Footer>
        </div>
      </Router>
    </CurrencyContext.Provider>
  );
};

export default App;

Verify the correct configuration of your .htaccess file which is used for configuring Apache web servers. It seems that you have included the necessary rules for rewriting URLs, but make sure the .htaccess file is located in the root directory of your application, alongside your index.html file. Also, confirm that mod_rewrite is enabled on your hosting server.

Try to check the basename in your Router component, what I mean by this is - in your App.js file, you're using the basename prop in the Router component from react-router-dom. Since you're hosting your app in a subdirectory on your domain, make sure the basename is set correctly. For example, if your app is hosted at https://quierotraspasarlo.com/app, the basename should be "/app".

  • Thank you for your answer. Actually, the app is hosted in "/", meaning that the initial page is just "https://quierotraspasarlo.com/". I also made sure that the rewrite module is enabled. I recorded a video on what is exactly happening to make it clear: https://drive.google.com/file/d/1Ilayf2ROfM3_88d0M4SiSOcvMNGGIWs1/view?usp=sharing The clickable elements only modify the URL, but do not refresh the page to display the new content. How can I solve it? – joangm_ Jul 04 '23 at 08:29