react-router icon indicating copy to clipboard operation
react-router copied to clipboard

[Bug]: Dynamic basename

Open ihmpavel opened this issue 3 years ago • 2 comments

What version of React Router are you using?

6.3.0

Steps to Reproduce

  1. Create basic router
const [basename, setBasename] = useState('de')
...
<Router basename={basename}>
  <Routes>
    <Route path="/one" element={<Component />} />
    <Route path='/two' element={<AnotherComponent />} />
  1. Navigate to /one (url will be /de/one) with <Link to='/one' />
  2. Navigate to /two (url will be /de/two) with <Link to='/two' />
  3. Call function, which will change basename (setBasename('en')) and url to /en/one (history.pushState('/en/one', '', '/en/one'))
  4. 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.
  5. 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

ihmpavel avatar Aug 23 '22 17:08 ihmpavel

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

sun0day avatar Aug 30 '22 02:08 sun0day

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

jmfrancois avatar Sep 16 '22 08:09 jmfrancois

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.

brophdawg11 avatar Jan 24 '23 18:01 brophdawg11