Мы заменяем react-router-doms HashRouter на BrowserRouter и хотели бы перенаправить старые маршруты на новые.
Я отметил nginx, потому что я не против сделать там редиректы. :)
Допустим, у нас есть старый маршрут /#/users и /#/users:id: они должны совпадать и перенаправлять на /users и /users/:id.
Пока я пробовал (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>
Первый маршрут совпадает и перенаправляется нормально. Второй (с id) проблематичен. Когда я перехожу к /#/users/123, он перенаправляется на /users/:id. Это замена фактического 123 на :id.
Это два примера маршрутов. У нас есть еще с параметрами для перенаправления.





Я думаю, для навигации вы используете что-то вроде этого,
<Link to = "/#/users" />
<Link to = "/#/users/123" />
Согласно документы,
A
<Router>that uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL.
При использовании HashRouter вам не нужно добавлять # вручную, маршрутизатор React автоматически добавляет # в URL
Так что ваши маршруты должны быть,
import { HashRouter } from 'react-router-dom'
<HashRouter>
<Switch>
<Route exact path='/users' component = {UsersComponent} />
<Route exact path='/users/:id' component = {UsersDashComponent} />
</Switch>
</HashRouter>
И ссылки должны быть,
<Link to = "/users" />
<Link to = "/users/123" />
Теперь перейдем к вашему вопросу, как заменить HashRouter на BrowserRouter?
Для этого вам просто нужно сделать это,
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>
И ваши ссылки должны быть одинаковыми.
Примечание: Также посмотрите, я добавил exact к route, это будет точно соответствовать path.
Итак, это не проблема реакции, а самого ngnix.
@ AlvMF1 Я обновил свой ответ. Убедитесь, что вы сначала написали <Redirect>, а затем на самом деле <Route>.
Неудачно. Ты пробовал? Меня перенаправляют только в том случае, если <Redirect> находится за пределами <Switch>, но, как говорится в вопросе, параметр - нет. Я получаю :id в качестве параметра...
Я не пробовал это, но в документах говорится только об этом - github.com/ReactTraining/react-router/blob/master/packages/…
Вот мое решение:
<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>
Только маршруты, имеющие /#, будут соответствовать /. Можно легко добавить условие, если необходимо отобразить что-то в корне.
Честно говоря, ни одно из этих решений мне не помогло, я хотел выполнить перенаправление со всех моих предыдущих маршрутов на новые без #.
Хотя принятый ответ должен подойти для большинства случаев, я также обрабатываю 404, которые на самом деле не будут обнаружены таким перенаправлением.
Закончилось добавлением охранника, взаимодействующего с историей React Router перед рендерингом моего переключателя:
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>
)
}
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
Вопрос о том, как перенаправить пользователей со старых хеш-ссылок на новые (без хеша)
вы можете прочитать вопрос еще раз, там написано, как перенаправить с хэша на браузер !!!
правильно. но ваше решение не перенаправляет пользователя с URL-адреса, например: «/#/product/1» на «/product/1». Также автор говорит: > Пользователи могут получить доступ к старым ссылкам с хешем в своих закладках, электронной почте, на других сайтах и т. д.
хорошо, @Max понял, что им нужно что-то вроде функциональности location.replace.
Спасибо за подробное объяснение. Однако на самом деле я вообще не использую
<Link>. Пользователи могут получить доступ к старым ссылкам с хэшем в своих закладках, электронной почте, на других сайтах и т. д.