React-Router Urls Don't Work When Refreshing or Writing Manually

Cannot refresh or writing manually the url with react-router

The reason why this is happening is your server does not know what to serve when you hit that URL. There are multiple approaches to solving your problem. I'll suggest the easiest approach here.

Replace BrowserRouter with HashRouter.

class App extends Component {
render() {
return (
<div>
<HashRouter basename="/ReactCalendar">
<Header/>
<Switch>
<Route exact path="/" component={Planning} />

<Route exact path="/creerActivite" component={CreerActivite} />
<Route exact path="/typesRDV" component={TypesRDV} />
</Switch>
</HashRouter>
<BackTop />
</div>
);
}
}

And obviously, don't forget to import HashRouter from 'react-router-dom'.

You can view other approaches here:
React-router urls don't work when refreshing or writing manually

React router. Cannot GET when refreshing a page or write url manually

This is documented (and now I have written 30 characters): https://github.com/reactjs/react-router/blob/v2.3.0/docs/guides/Histories.md#browserhistory

Why do I have to manually refresh the page for the component to load when using react-router?

Issue

Your app code is actually crashing when navigating away from a page. It's not clear why you aren't seeing the React error page (perhaps you are running a production build) but the issue is that for each page you are using a useEffect hook to set a timeout to update some local state.

useEffect(() => {
return setTimeout(() => {
setLetterClass('text-animate-hover');
}, 3000);
}, []);

The issue with this is that React assumes that anything returned from the useEffect hook is a cleanup function to be invoked when the component is rerendering/unmounting. setTimeout returns a number representing the timer id.

Reloading the page is effectively reloading the entire app on the current URL path.

Solution

On each of these pages, refactor the logic to return a cleanup function that clears the timeout.

useEffect(() => {
const timer = setTimeout(() => {
setLetterClass('text-animate-hover');
}, 3000);
return () => clearTimeout(timer);
}, []);

This allows the timeout to be instantiated when the component mounts, and for the offhand chance the user navigates away from the page and this component unmounts, it will clear the timeout and won't invoke the callback that will enqueue a state state.

Suggestion

It seems that each of these pages has the same animation letterClass state for the AnimatedLetters component. Instead of duplicating the same code/logic across all pages, abstract it into a custom React hook that returns the letterClass value.

Example:

const useLetterClass = ({
start = 'text-animate',
end = 'text-animate-hover'
}) => {
const [letterClass, setLetterClass] = useState(start);

useEffect(() => {
const timer = setTimeout(() => {
setLetterClass(end);
}, 3000);
return () => clearTimeout(timer);
}, []);

return { letterClass };
};

In each page component import the useLetterClass hook, call, and pass the returned letterClass prop value.

Example:

const Contact = () => {
const { letterClass } = useLetterClass({
start: 'text-animate',
end: 'text-animate-hover',
});
const form = useRef();

const sendEmail = (e) => {
...
}

return (
<>
<div className="container contact-page">
<div className="text-zone">
<h1>
<AnimatedLetters
letterClass={letterClass}
strArray={['C', 'o', 'n', 't', 'a', 'c', 't', ' ', 'm', 'e']}
idx={15}
/>
</h1>
...
</div>
</div>
<Loader type="ball-scale" />
</>
);
};

Edit why-do-i-have-to-manually-refresh-the-page-for-the-component-to-load-when-using

The sandbox code you provided also seems to have an issue with some of the SCSS, specifically with a $sidebar-color variable missing. I'm not familiar with SCSS much, but I don't suspect it is related to the routing/navigation issue I described above.

React-router-dom V6 don't change route correctly (refresh - f5 page is required)

Move the Header component into the Router so the Link components it renders are working and updating the same routing context the routes are rendered in. There should have been an invariant warning/error regarding rendering the Link components outside a Router. If there is no such error/warning this is indicative of rendering the links into a separate router/routing context. You need only a single router for the entire app, so remove any other extraneous routers you might have in your app.

Example:

function App() {
return (
<div className="app">
<Router>
<Header /> // <-- move into Router
<Routes>
<Route path="/" element={<Content />} />
<Route path="/product" element={<Product />} />
<Route path="/contact" element={<Contact />} />
<Route path="/cart" element={<Cart />} />
</Routes>
</Router>
<Footer />
</div>
);
}

Deployed React App to IONOS - 404 on page refresh

Firebase, GitHub Pages, Surge, Now and Netlify all use 404.html to serve you soft 404s. I believe your hosting might be a LAMP Stack Hosting.

Please use the following .htaccess if it's supported or something similar to redirect all the requests to index.html:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]

Learn more about this here:

  • React-router URLs don't work when refreshing or writing manually
  • The Ultimate Guide to .htaccess Files


Related Topics



Leave a reply



Submit