Reputation: 170
We're replacing react-router-dom
s HashRouter
with BrowserRouter
and would like to redirect old routes to the new ones.
I tagged nginx
because I don't mind making redirects there. :)
So say we have an old route /#/users
and /#/users:id
: They should match and redirect to /users
and /users/:id
.
So far I tried (react-router-dom v5.0.1
):
<Router>
<Switch>
<Route path='/users' component={UsersComponent} />
<Route path='/users/:id' component={UsersDashComponent} />
</Switch>
<Redirect from='/#/users' to '/users' />
<Redirect from='/#/users/:id' to='/users/:id' />
</Router>
The first route matches and redirects fine. The second one (with the id
) is problematic. When I navigate to /#/users/123
it redirects to /users/:id
. It's replacing the actual 123
with :id
.
Those are two examples of routes. We have more with params to redirect as well.
Upvotes: 7
Views: 15569
Reputation: 33
export const history = createBrowserHistory();
export const App: FC = () => {
return (
<Router history={history}>
<Switch>
<Route path="/settings" exact component={Settings} />
</Switch>
</Router>
);
};
export const Settings : FC = () => {
return (
<HashRouter basename="/" hashType="noslash">
<Switch>
<Route path="/profile">
<Profile />
</Route>
</Switch>
</HashRouter>
);
};
import {history} from "./App.tsx";
export const Profile : FC = () => {
return (
<Router history={history}>
<Link to="/product/1"/>
</Router>
);
};
// It's simple store your history in a variable and make use of it
Upvotes: 0
Reputation: 2887
To be honest, none of these solutions worked for me really, I wanted to perform a redirect from all my previous routes to the new ones without #
.
While the accepted answer should be fine for most cases, I'm also handling 404s, which would not really be caught by such redirect.
Ended up adding a guard interacting with React Router history before rendering my switch:
function App() {
const history = useHistory()
if (location.hash.startsWith('#/')) {
history.push(location.hash.replace('#', '')) // or history.replace
}
return (
<Switch>
<Route path="/" exact component={ Home } />
...
<Route path="*" component={ PageNotFound } />
</Switch>
)
}
Upvotes: 6
Reputation: 170
Here's my solution:
<Router>
<Switch>
<Route path='/users' component={UsersComponent} />
<Route path='/users/:id' component={UsersDashComponent} />
<Route exact path='/' render={({ location }) => <Redirect to={location.hash.replace('#', '')} />} />
</Switch>
</Router>
Only routes that have /#
will match /
. One could easily add a conditional if needed to render something on root.
Upvotes: 0
Reputation: 20765
I think for navigation you are using something like this,
<Link to="/#/users" />
<Link to="/#/users/123" />
As per docs,
A
<Router>
that uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL.
When using HashRouter
you don't need to prepend #
manually React router automatically adds #
in URL
So your routes must be,
import { HashRouter } from 'react-router-dom'
<HashRouter>
<Switch>
<Route exact path='/users' component={UsersComponent} />
<Route exact path='/users/:id' component={UsersDashComponent} />
</Switch>
</HashRouter>
And links should be,
<Link to="/users" />
<Link to="/users/123" />
Now coming to your question, how to replace HashRouter
with BrowserRouter
?
To do so you just need to do this,
import { BrowserRouter } from 'react-router-dom'
<BrowserRouter>
<Switch>
<Redirect from='/#/users' to '/users' />
<Redirect from='/#users/:id' to='/users/:id' />
<Route exact path='/users' component={UsersComponent} />
<Route exact path='/users/:id' component={UsersDashComponent} />
</Switch>
</BrowserRouter>
And your links should be same.
Note: Also have a look I have added exact
to route
, it will match the exact path
.
Upvotes: 3