У меня есть несколько кнопок, которые действуют как маршруты. Каждый раз, когда маршрут изменяется, я хочу убедиться, что активная кнопка изменяется.
Есть ли способ прослушать изменения маршрута в ответном маршрутизаторе v4?
У меня есть несколько кнопок, которые действуют как маршруты. Каждый раз, когда маршрут изменяется, я хочу убедиться, что активная кнопка изменяется.
Есть ли способ прослушать изменения маршрута в ответном маршрутизаторе v4?
Я использую withRouter
для получения location
prop. Когда компонент обновляется из-за нового маршрута, я проверяю, изменилось ли значение:
@withRouter
class App extends React.Component {
static propTypes = {
location: React.PropTypes.object.isRequired
}
// ...
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
this.onRouteChanged();
}
}
onRouteChanged() {
console.log("ROUTE CHANGED");
}
// ...
render(){
return <Switch>
<Route path="/" exact component={HomePage} />
<Route path="/checkout" component={CheckoutPage} />
<Route path="/success" component={SuccessPage} />
// ...
<Route component={NotFound} />
</Switch>
}
}
Надеюсь, что это поможет
Чтобы расширить вышесказанное, вам нужно добраться до объекта истории. Если вы используете BrowserRouter
, вы можете импортировать withRouter
и обернуть свой компонент компонентом высшего порядка (HoC), чтобы иметь доступ через свойства к свойствам и функциям объекта истории.
import { withRouter } from 'react-router-dom';
const myComponent = ({ history }) => {
history.listen((location, action) => {
// location is an object like window.location
console.log(action, location.pathname, location.state)
});
return <div>...</div>;
};
export default withRouter(myComponent);
Единственная вещь, о которой нужно знать, - это то, что с помощью Router и большинства других способов доступа к history
кажется, загрязняется реквизит, поскольку они деструктурируют объект в нем.
Вы должны использовать историю v4 lib.
Пример оттуда
history.listen((location, action) => {
console.log('The current URL is ${location.pathname}${location.search}${location.hash}')
console.log('The last navigation action was ${action}')
})
В некоторых случаях вы можете использовать атрибут render
вместо component
следующим образом:
class App extends React.Component {
constructor (props) {
super(props);
}
onRouteChange (pageId) {
console.log(pageId);
}
render () {
return <Switch>
<Route path="/" exact render={(props) => {
this.onRouteChange('home');
return <HomePage {...props} />;
}} />
<Route path="/checkout" exact render={(props) => {
this.onRouteChange('checkout');
return <CheckoutPage {...props} />;
}} />
</Switch>
}
}
Обратите внимание, что при изменении состояния в методе onRouteChange
это может привести к ошибке "Максимальная глубина обновления превышена".
С крючками:
import { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { history as historyShape } from 'react-router-prop-types'
const DebugHistory = ({ history }) => {
useEffect(() => {
console.log('> Router', history.action, history.location])
}, [history.location.key])
return null
}
DebugHistory.propTypes = { history: historyShape }
export default withRouter(DebugHistory)
Импортировать и отобразить как компонент <DebugHistory>