AWS S3 and React Router don't play well together. There is a good solution that works with older versions of React Router as found in https://stackoverflow.com/a/61375930/15019760
Right now, my AWS Redirect config is:
[
{
"Condition": {
"HttpErrorCodeReturnedEquals": "404"
},
"Redirect": {
"HostName": "myhostname.com",
"ReplaceKeyPrefixWith": "#!/"
}
},
{
"Condition": {
"HttpErrorCodeReturnedEquals": "403"
},
"Redirect": {
"HostName": "myhostname.com",
"ReplaceKeyPrefixWith": "#!/"
}
}
]
This adds "#!" to the URL, so we need the router to get rid of that.
In the old React Router, we could do this by
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from "react-router-dom";
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { render } from 'react-dom';
import { createBrowserHistory } from 'history';
import App from './App';
const history = createBrowserHistory();
let app = document.getElementById('app');
if (app) {
// 1. Set up the browser history with the updated location
// (minus the # sign)
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
history.replace(path);
}
// 2. Render our app
render(<App />, app);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App/>
</BrowserRouter>
</React.StrictMode>
);
However, "history" has now been replaced with useNavigate(), as far as I'm aware.
So then, I tried something like this:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, useNavigate } from "react-router-dom";
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const Index = () => {
const navigate = useNavigate();
React.useEffect(() => {
// 1. Set up the browser history with the updated location
// (minus the # sign)
const locationHash = window.location.hash;
const path = (/#!(\/.*)$/.exec(locationHash) || [])[1];
if (path) {
navigate(path, { replace: true });
}
}, [navigate]);
return (
<React.StrictMode>
<BrowserRouter>
<App/>
</BrowserRouter>
</React.StrictMode>
);
};
ReactDOM.createRoot(document.getElementById('root')).render(<Index />);
However, this doesn't work because "useNavigate() may be used only in the context of a component."
How should I proceed? Is there some other solution I should try?
(Note, I want to avoid the "hacky" solution of setting the Error page to index.html, given the concerns with SEO mentioned by others.