Yanıtlar:
Prop withRouteralmak için kullanırım location. Bileşen yeni bir rota nedeniyle güncellendiğinde, değerin değişip değişmediğini kontrol ederim:
@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>
}
}
Umarım yardımcı olur
withRouterama hata alıyorum You should not use <Route> or withRouter() outside a <Router>. <Router/>Yukarıdaki kodda herhangi bir bileşen görmüyorum . Peki nasıl çalışıyor?
<Switch>bileşen fiili yönlendirici görevi görüyor. Yalnızca <Route>eşleşen bir yola sahip olan ilk giriş işlenecektir. <Router/>Bu senaryoda herhangi bir bileşene gerek yok
Yukarıdakileri genişletmek için geçmiş nesnesine gitmeniz gerekir. Kullanıyorsanız , geçmiş nesnesinin özelliklerine ve işlevlerine props aracılığıyla erişim sağlamak için bileşeninizi daha yüksek dereceli bir bileşenle (HoC)BrowserRouter içe aktarabilir withRouterve sarabilirsiniz .
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);
Dikkat edilmesi gereken tek şey, Router ve diğer birçok yolla historynesnenin yapısını bozarken nesneyi kirletmesidir.
withRoutesiçin withRouter.
History v4 lib kullanmalısınız .
Oradan örnek
history.listen((location, action) => {
console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`)
console.log(`The last navigation action was ${action}`)
})
history.pushtetikleyici gibi görünüyor history.listen. Geçmiş v4 belgelerinde Temel URL kullanma örneğine bakın . Bu aslında bir tarayıcının yerel nesnesinin bir sarmalayıcısı olduğundan, tam olarak yerel olan gibi davranmaz. historyhistory
const unlisten = history.listen(myListener); unlisten();
withRouter, history.listenve useEffect(React Hooks) birlikte oldukça güzel çalışıyor:
import React, { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
const Component = ({ history }) => {
useEffect(() => history.listen(() => {
// do something on route change
// for my example, close a drawer
}), [])
//...
}
export default withRouter(Component)
Dinleyici geri araması, bir rota değiştirildiğinde her seferinde tetiklenir ve bunun dönüşü history.listen, iyi bir şekilde oynayan bir kapatma işleyicisidir useEffect.
v5.1 kullanışlı kancayı tanıtıyor useLocation
https://reacttraining.com/blog/react-router-v5-1/#uselocation
import { Switch, useLocation } from 'react-router-dom'
function usePageViews() {
let location = useLocation()
useEffect(
() => {
ga.send(['pageview', location.pathname])
},
[location]
)
}
function App() {
usePageViews()
return <Switch>{/* your routes here */}</Switch>
}
Cannot read property 'location' of undefined at useLocation. UseLocation () çağrısının, yönlendiriciyi ağaca yerleştiren aynı bileşende olmadığından emin olmanız gerekir: buraya bakın
Kancalı:
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>Bileşen olarak içe aktar ve işle
import React, { useEffect } from 'react';
import { useLocation } from 'react-router';
function MyApp() {
const location = useLocation();
useEffect(() => {
console.log('route has been changed');
...your code
},[location.pathname]);
}
kancalı
Bazı durumlarda şu şekilde renderyerine öznitelik kullanabilirsiniz 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>
}
}
onRouteChangeYöntemdeki durumu değiştirirseniz , bunun 'Maksimum güncelleme derinliği aşıldı' hatasına neden olabileceğine dikkat edin .
React Hooks ile kullanıyorum useEffect
const history = useHistory()
const queryString = require('query-string')
const parsed = queryString.parse(location.search)
const [search, setSearch] = useState(parsed.search ? parsed.search : '')
useEffect(() => {
const parsedSearch = parsed.search ? parsed.search : ''
if (parsedSearch !== search) {
// do some action! The route Changed!
}
}, [location.search])
useEffectKanca ile bir dinleyici eklemeden rota değişikliklerini tespit etmek mümkündür.
import React, { useEffect } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import Main from './Main';
import Blog from './Blog';
const App = ({history}) => {
useEffect( () => {
// When route changes, history.location.pathname changes as well
// And the code will execute after this line
}, [history.location.pathname]);
return (<Switch>
<Route exact path = '/' component = {Main}/>
<Route exact path = '/blog' component = {Blog}/>
</Switch>);
}
export default withRouter(App);
Bu problemle az önce uğraştım, bu yüzden verilen diğer cevaplara ek olarak çözümümü ekleyeceğim.
Buradaki sorun useEffect, çağrı yalnızca ilk işlemden sonra tetiklendiğinden, istenmeyen bir gecikme olduğundan, gerçekten istediğiniz gibi çalışmamasıdır.
Redux gibi bir durum yöneticisi kullanırsanız, mağazadaki durum nedeniyle ekranda bir titreme yaşama ihtimaliniz vardır.
useLayoutEffectBu hemen tetiklendiği için gerçekten istediğiniz şey kullanmaktır .
Bu yüzden yönlendiricimle aynı dizine koyduğum küçük bir yardımcı program işlevi yazdım:
export const callApis = (fn, path) => {
useLayoutEffect(() => {
fn();
}, [path]);
};
HOC bileşeni içinden şöyle çağırıyorum:
callApis(() => getTopicById({topicId}), path);
pathmatchkullanılırken nesnede geçirilen prop withRouter.
Tarihi elle dinlemekten / dinlemekten gerçekten yana değilim. Bu sadece imo.