Gareth D.
—When using React Router for client-side routing in your single page application (SPA), you may run into the issue of URL routes not working when a page is refreshed, the URL is written manually, or when the URL is shared. This issue may be due to your browser making a GET request to your server for a route that is not handled on your server. You have client-side routing set up, but you don’t have server-side routing set up.
This issue occurs for routes that are not on the home page /
route. For example, if you navigate to one of your client-side routes, such as the /contact
page, and then refresh the page, your app will crash and you’ll see the following error message on your page:
Cannot GET /contact
When your app first loads, a GET request is made to your server, which gets the JavaScript code for React and React Router. Once the JavaScript is loaded in your browser, React Router takes control of routing. If you haven’t set up server-side routing, the JavaScript code can only be fetched from the /
route on your server.
React Router handles route changes on the client. It does not make a request to your server on every route change. It uses the browser’s history
API to change the URL for a route client-side and it renders the view for that route. This is different to server-side routing, where a GET request is made to the server on each route change. This causes a page refresh as a new page is fetched.
To fix the issue, it’s best to add some logic on your server to handle server-side routing. You can set up server routing for each route or you can re-direct all server requests to the /
route index.html
file. You can also set up client-side routing such that it only makes requests to the /
server route.
You can use a hash router instead of a browser router to make all client-side requests go to the same /
server route. It works by appending a #
to the end of your URL root. Anything after the #
won’t be sent to the server. So if you send someone a link to https://www.yourwebsite/#/contact
, the browser will make a GET request to https://www.yourwebsite/
and the React Router hash router will show the /contact
page. The React Router docs recommend that you don’t use hash URLs. Only use hash URLs if you can’t configure your server to direct all traffic to your React Router application.
If you have control over the server that you are using, setting up a catch-all route is a good solution. You can redirect all requests to the /
route index.html
file. It has the same result as the hash history strategy but without the hashes in the client-side URLs. Here’s an example of a catch-all route in an Express.js app:
app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "dist/index.html"), function (err) { if (err) { res.status(500).send(err); } }); });
You may be using a hosting service that supports client-side routing and uses a serverless backend, such as Netlify. In this case, you’ll need to configure the app as a SPA so that all requests are re-directed to the /
route. This setup may be part of a question asked by the hosting service during set up or you may need to change some configuration files yourself. The steps for this should be available in the hosting provider’s docs.
You can set up your server to return pages for specific routes that are important for SEO or for all routes. This adds more complexity and you may end up with duplicate code on the client and the server. If SEO is a concern, it may be best to use a React framework that has server-side rendering or static site generation such as Next.js, Remix, or Gatsby.
If you’re looking to get a deeper understanding of how React application monitoring works, take a look at the following articles:
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.