Fixing react-router “Cannot GET/{url}” on page refresh.

Imagine you are writing an app with React and you have everything wired with React-Router. Your little app runs fine until you send your colleague the absolute url of a new “page” you have been working on. Let’s say it is www.example.com/products. Then you get an email back: “Hey, I cannot open this. I get an error: “Cannot GET/products”. Oh, the embarrassment!

Ok, here is what happens. Back in the you made a request to the backend, it “routes” to the requested resource and then it served the products page. But now with libraries like Angular and React, routing happens on the frontend, because of javascript’s history.pushState(). This means that the frontend can render the new page without a refresh.

This is all good when you initially request the site at /, which will serve back react and all its components and packages and react-router will start handling the routing for you. But if you initially ask for /products, if your server is not set to handle that request it will return resource not found 404.

So here is what we could do to fix this:

Hash History

Using urls with #. Requesting www.example.com/#/products will request all the react files from / but then it will call /products.

Downside: Ugly urls and poor CEO.

Catch All

This approach will route all the requests on the backend to /. It is quite easy to implement. Here is the nginx example:

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

Downside: this is still not great for CEO

Isomorphic

If one can run Node.js on the server and have the routes mapped one-to-one, with the same react-router config, they could return the same markup from the backend and it would end up as if the page transition has happened on the frontend.

This would be the holy grail for SEO but also the hardest to set.

Used resources:

chevron_left

Leave a comment

Your email address will not be published. Required fields are marked *

Comment
Name
Email
Website