Главный ответ здесь, хотя и решает проблему OP, вероятно, не является решением, которое нужно большинству людей, поскольку он отключает наиболее важную функцию доступности маршрутизатора Reach.
Тот факт, что маршрутизатор Reach фокусирует содержимое совпадающего <Route>
на изменении маршрута, составляет по соображениям доступности - поэтому средства чтения с экрана и т. Д. Могут быть направлены на недавно обновленное релевантное содержимое при переходе к новая страница.
Для этого используется HTMLElement.focus()
- см. Документы MDN здесь .
Проблема в том, что по умолчанию эта функция прокручивается до фокусируемого элемента. - это аргумент preventScroll
, который можно использовать, чтобы отключить это поведение, но поддержка браузера его не очень хороша, и независимо от этого, Reach Router не использует его.
Подставка primary
на Router
используется, чтобы отключить это поведение для любых вложенных <Router>
, которые у вас могут быть - это , а не , предназначенные для использования на вашем основной (основной) <Router>
- отсюда и название.
Установка этого false
на вашем основном <Router>
, как подсказывает верхний ответ, «работает» в том смысле, что он останавливает поведение прокрутки , но это достигается простым отключением фокусировки. поведение полностью, что нарушает функцию доступности. Как я уже сказал, если вы сделаете это, вы нарушите одну из основных причин использования Reach Router.
Итак, в чем решение?
По сути, кажется, что этот побочный эффект HTMLElement.focus()
- прокрутка к сфокусированному элементу - неизбежна. Поэтому, если вам нужна функция специальных возможностей, вы должны использовать прокрутку.
Но с учетом сказанного может быть обходной путь. Если вы будете прокручивать вручную верхнюю часть страницы, используя window.scrollTo(0, 0)
при каждом изменении маршрута, я считаю, что это не «нарушит» функцию фокусировки с точки зрения доступности, но «исправит» поведение прокрутки с точки зрения UX.
Конечно, это немного хакерский и обязательный обходной путь, но я думаю, что это лучшее (возможно, единственное) решение этой проблемы без нарушения доступности.
Вот как я это реализовал
class OnRouteChangeWorker extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
this.props.action()
}
}
render() {
return null
}
}
const OnRouteChange = ({ action }) => (
{/*
Location is an import from @reach/router,
provides current location from context
*/}
<Location>
{({ location }) => <OnRouteChangeWorker location={location} action={action} />}
</Location>
)
const Routes = () => (
<>
<Router>
<LayoutWithHeaderBar path="/">
<Home path="/" />
<Foo path="/foo" />
<Bar path="/bar" />
</LayoutWithHeaderBar>
</Router>
{/*
must come *after* <Router> else Reach router will call focus()
on the matched route after action is called, undoing the behaviour!
*/}
<OnRouteChange action={() => { window.scrollTo(0, 0) } />
</>
)