Reputation: 55
I've looked through other answers and tried the solutions but I"m still getting a bit confused.
I've got a url, say www.sitename.com
and I've got a React app using react-router-dom
to do the routing.
<Router>
<Route
path={process.env.PUBLIC_URL + "/"}
exact={true}
component={Home}
/>
<Route path={process.env.PUBLIC_URL + "/about"} component={About} />
<Route
path={process.env.PUBLIC_URL + "/projects"}
component={Projects}
/>
<Route path={process.env.PUBLIC_URL + "/contact"} component={Contact} />
</Router>
I've imported HashRouter as Router in this project.
Other answers I've read say that this will solve the problem I was having of when a page is reloaded, the browser wouldn't be able to display anything as, for example, there was no content at www.sitename.com/about
as the rendering was controlled from the index.html
page.
Using the hash router did solve the problem, but now I can't direct people to www.sitename.com/about
as that page still doesn't exist, React seems to make the URL www.sitename.com/#/about
I've read the docs but can't seem to find an answer that makes sense to me!
Upvotes: 4
Views: 3670
Reputation: 944005
When you are writing a single page application, you aren't really navigating between different HTML documents. Instead, you modify the DOM to show different data.
This looks like different pages, but isn't really. This caused all sorts of problems because the browser's back button didn't work and you didn't have different URLs for different "pages".
As a hack, people changed the fragment identifier portion of the page and used JavaScript to work out which section of the SPA should be displayed. As a result, it will put #
s in the URL so you can't have a URL with /about
but have #/about
instead.
This is what HashRouter
does. If you just link to #/about
it will work.
Browser vendors reacted to this by adding the History API. This provides mechanisms to insert URLs into the browser history and get all the benefits of # based navigation with nice URLs.
It is designed to be used in conjunction with server-side code which has the same effect as the DOM manipulation the JavaScript does.
So if you click a link to /about
:
/about
but if you visit /about
directly then the server generates the about page instead.
This provides good food for search engines and content that is accessible even if the JavaScript fails.
It is also more work since you need to make the server duplicate the work of the client. Happily, there are tools to make this easy. A couple of populate ones are next.js which uses isomorphic JavaScript to make the client-side React code run on the server as well and Gatsby which generates static pages at build time so you can use static hosting.
They have their own Router modules to use instead of HashRouter.
If you want to use URLs without a #
, pages which work even when JavaScript fails, and a bonus to SEO: Use one of those approaches.
There is also the cheap and dirty hack approach which is to configure your HTTP server to serve up the basic HTML document which loads the React JS for every URL which isn't a static file.
This then makes it the responsibility of the client-side code to look at the URL and work out what content to show (in the same way that HashRouter does). It also tends to cause lots of URLs which should be 404 errors to return 200 and that basic HTML document.
You'd switch out HashRouter for BrowserRouter if you did this.
Upvotes: 3
Reputation: 4479
The problem is that, when a client (the browser) ask for a page to the server (for example /about
) and this page does not exists in the server, it gives a 404.
To solve this problem you should configure your server to return you, for every request, the /index.html
file that is aware of react-router-dom routing.
To configure your server, assuming you are using Apache, you should follow this answer (you can find similar tutorials also for other web servers):
How to setup apache server for React route?
You can find more info at this link:
https://developer.mozilla.org/en-US/docs/Web/API/History
Upvotes: 1