react-router
react-router copied to clipboard
[Bug]: Dynamic basename
What version of React Router are you using?
6.3.0
Steps to Reproduce
- Create basic router
const [basename, setBasename] = useState('de')
...
<Router basename={basename}>
<Routes>
<Route path="/one" element={<Component />} />
<Route path='/two' element={<AnotherComponent />} />
- Navigate to
/one(url will be/de/one) with<Link to='/one' /> - Navigate to
/two(url will be/de/two) with<Link to='/two' /> - Call function, which will change basename (
setBasename('en')) and url to/en/one(history.pushState('/en/one', '', '/en/one')) - Navigate back in browser - An error
<Router basename="/en"> is not able to match the URL "/de" because it does not start with the basename, so the <Router> won't render anything. - White screen in console
Expected Behavior
There should be an easy way, how to handle dynamic basenames in v6, as it was in v5.
Router should handle back button fine and should render component.
Actual Behavior
After navigating back after basename change, there is white screen
I dont think this is a bug. You should handle dynamic basename changing situation before you pass it to react-router. Maybe you can determine what basename should be via location.pathname
It comes from history major change. The previous history was managing that https://github.com/remix-run/history/releases/tag/v5.0.0
Removed relative pathname support in hash history and memory history
I do not understand this change which make route change by API a nightmare. This do not respect 12 factors at all, you have to code with environment in mind.
history was the low level layer so the perfect place to support it. Move the basename support at higher level (in react-router) is bad by design
Call function, which will change basename (setBasename('en')) and url to /en/one (history.pushState('/en/one', '', '/en/one'))
React Router doesn't support direct external navigation using history.pushState, you should be navigating through react router's Link/useNavigate APIs.
For this use case, I would suggest using a root route of <Route path=":lang"> to manage the language code in your URLs.