If you are using React Router in a React app, you might encounter an HTTP 404 - Not Found
error when you refresh or reload a non root (/
) URL.
Why does this happen?
By default, web servers and object storage providers serve files from the disk. So when you go to the root /
URL, it will try to serve index.html
and if you go to /about-us
it will serve /about-us/index.html
.
We usually build single-page applications or SPAs with React. SPAs use Javascript to show different content within a single web page. So when you create a production build of a React app, it only generates a single index.html
file with references to the Javascript and CSS files necessary to run the React app. Even when we declare several Routes with React Router, only a single index.html
file is generated since it uses Javascript to show different Routes within a single page.
So the 404 error occurs because the web server is trying to load different web pages and React SPAs only consist of a single index.html
web page.
How to fix it
To fix this problem, we need to configure our web server or object storage to serve index.html
for every single path used by React Router. Then when an app is loaded, React Router will read the path and show the Route that is supposed to be displayed at that path.
The easiest way to do this is to configure the web server to serve index.html
whenever it receives a URL that refers to a non-existent file. This way, the web server would be able to serve the CSS, JS and other files referenced from index.html
correctly since they exist on the disk and return index.html
for all the React Router paths which don't have any files.
Nginx and other web servers
This technique of returning different content for URLs is called URL rewriting and if you use Nginx, you can find how to setup it up to work with React Router in this post.
Netlify
You can use Netlify's rewrite feature to serve index.html
for all React router paths. This post will walk you through how you can set it up.
AWS S3 and object storage providers
If you are using AWS S3 or an object storage provider like Linode, you can achieve the same result by setting the error page to index.html
. This way, the object storage will show index.html
whenever a nonexistent file is requested which would start React and allow React Router to show the Route at that path.
For AWS S3, you can set the error page using the AWS Management Console. Go to your S3 Bucket, "Properties" and click "Edit" in the "Static website hosting" section at the bottom. Next, enter index.html
as the "Error document" and click "Save changes" at the bottom.
If you are using Linode or another S3-compatible object storage provider, you can use s3cmd
to set the error page with the following command. Replace
$ s3cmd ws-create --ws-index=index.html --ws-error=index.html s3://<bucket-name>
AWS CloudFront
If you are using AWS CloudFront, the Error page can be configured under the Error Pages tab in the CloudFront section of the AWS Management Console. Note that you should setup error pages for both 403 and 404 error codes.