Tarama geçmişine bağlı olarak bazı iş mantığı uygulamalıyım.
Yapmak istediğim şey şuna benzer:
reactRouter.onUrlChange(url => {
this.history.push(url);
});
URL güncellendiğinde react-router'dan geri arama almanın bir yolu var mı?
Tarama geçmişine bağlı olarak bazı iş mantığı uygulamalıyım.
Yapmak istediğim şey şuna benzer:
reactRouter.onUrlChange(url => {
this.history.push(url);
});
URL güncellendiğinde react-router'dan geri arama almanın bir yolu var mı?
Yanıtlar:
Sen yararlanabilir history.listen()
rota değişikliği algılamak için çalışırken işlevi. Kullandığınızı göz önünde bulundurarak , pervaneye erişmek için react-router v4
bileşeninizi withRouter
HOC ile sarın history
.
history.listen()
bir unlisten
işlev döndürür . Bunu unregister
dinlemek için kullanırsın.
Rotalarınızı şu şekilde yapılandırabilirsiniz:
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
ve ardından AppContainer.js'de
class App extends Component {
componentWillMount() {
this.unlisten = this.props.history.listen((location, action) => {
console.log("on route change");
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<div>{this.props.children}</div>
);
}
}
export default withRouter(App);
Tarih belgelerinden :
Aşağıdakileri kullanarak mevcut konumdaki değişiklikleri dinleyebilirsiniz
history.listen
:
history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })
Location nesnesi, window.location arayüzünün bir alt kümesini uygular, örneğin:
**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment
Konumlar ayrıca aşağıdaki özelliklere sahip olabilir:
location.state - Bu konum için URL'de bulunmayan bazı ekstra durumlar (
createBrowserHistory
ve içinde desteklenircreateMemoryHistory
)
location.key
- Bu konumu temsil eden benzersiz bir dize (createBrowserHistory
vecreateMemoryHistory
)İşlem,
PUSH, REPLACE, or POP
kullanıcının mevcut URL'ye nasıl ulaştığına bağlıdır.
Tepki-yönlendirici kullanıldığında zaman yararlanabilirler V3 history.listen()
gelen history
, yukarıda belirtildiği gibi bir paket veya da yararlanabilirbrowserHistory.listen()
Rotalarınızı şu şekilde yapılandırabilir ve kullanabilirsiniz:
import {browserHistory} from 'react-router';
class App extends React.Component {
componentDidMount() {
this.unlisten = browserHistory.listen( location => {
console.log('route changes');
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<Route path="/" onChange={yourHandler} component={AppContainer}>
<IndexRoute component={StaticContainer} />
<Route path="/a" component={ContainerA} />
<Route path="/b" component={ContainerB} />
</Route>
)
}
}
react-router v4
"
withRouter
history.listen()
kullanırken withRouter
zaten her zaman yönlendirme gerçekleşir yeni sahne ile bileşenini günceller? Değiştiyse yapmanız gereken herhangi bir şeyi gerçekleştirmek için nextProps.location.href === this.props.location.href
in componentWillUpdate
ile basit bir karşılaştırma yapabilirsiniz.
React Router 5.1 için güncelleme.
import React from 'react';
import { useLocation, Switch } from 'react-router-dom';
const App = () => {
const location = useLocation();
React.useEffect(() => {
console.log('Location changed');
}, [location]);
return (
<Switch>
{/* Routes go here */}
</Switch>
);
};
history
Nesneyi global olarak dinlemek istiyorsanız , onu kendiniz yaratmanız ve Router
. Daha sonra listen()
yöntemiyle dinleyebilirsiniz :
// Use Router from react-router, not BrowserRouter.
import { Router } from 'react-router';
// Create history object.
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
// Listen to history changes.
// You can unlisten by calling the constant (`unlisten()`).
const unlisten = history.listen((location, action) => {
console.log(action, location.pathname, location.state);
});
// Pass history to Router.
<Router history={history}>
...
</Router>
Geçmiş nesnesini bir modül olarak oluşturursanız daha da iyi, böylece ihtiyacınız olan her yere kolayca içe aktarabilirsiniz (örn. import history from './history';
react-router v6
Gelecek v6'da bu, useLocation
ve useEffect
kancaları birleştirerek yapılabilir.
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation()
React.useEffect(() => {
// runs on location, i.e. route, change
console.log('handle route change here', location)
}, [location])
...
}
Uygun yeniden kullanım için bunu özel bir useLocationChange
kancada yapabilirsiniz
// runs action(location) on location, i.e. route, change
const useLocationChange = (action) => {
const location = useLocation()
React.useEffect(() => { action(location) }, [location])
}
const MyComponent1 = () => {
useLocationChange((location) => {
console.log('handle route change here', location)
})
...
}
const MyComponent2 = () => {
useLocationChange((location) => {
console.log('and also here', location)
})
...
}
Değişiklik sırasında önceki rotayı da görmeniz gerekiyorsa, bir usePrevious
kancayla birleştirebilirsiniz.
const usePrevious(value) {
const ref = React.useRef()
React.useEffect(() => { ref.current = value })
return ref.current
}
const useLocationChange = (action) => {
const location = useLocation()
const prevLocation = usePrevious(location)
React.useEffect(() => {
action(location, prevLocation)
}, [location])
}
const MyComponent1 = () => {
useLocationChange((location, prevLocation) => {
console.log('changed from', prevLocation, 'to', location)
})
...
}
İlk müşteri rotasında yukarıdaki tüm yangının ve sonraki değişikliklerin olduğuna dikkat etmek önemlidir . Bu bir sorunsa, ikinci örneği kullanın ve prevLocation
herhangi bir şey yapmadan önce bir var olup olmadığını kontrol edin .
location
burada açıklığa kavuşturmak için tarayıcının konumu, yani her bileşende aynı ve bu anlamda her zaman doğru. Kancayı farklı bileşenlerde kullanırsanız, konum değiştiğinde hepsi aynı değerleri alır. Sanırım bu bilgilerle yaptıkları farklı olacak, ancak her zaman tutarlıdır.
Bu eski bir sorudur ve bir rota değişikliğini gerçekleştirmek için rota değişikliklerini dinlemenin iş ihtiyacını tam olarak anlamıyorum; dolambaçlı görünüyor.
AMA, tek istediğiniz şey 'page_path'
google analytics / global site etiketi / benzer bir şey için bir react-router rota değişikliğini güncellemek olduğu için burada sona erdiyseniz , işte şimdi kullanabileceğiniz bir kanca . Kabul edilen cevaba göre yazdım:
useTracking.js
import { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
export const useTracking = (trackingId) => {
const { listen } = useHistory()
useEffect(() => {
const unlisten = listen((location) => {
// if you pasted the google snippet on your index.html
// you've declared this function in the global
if (!window.gtag) return
window.gtag('config', trackingId, { page_path: location.pathname })
})
// remember, hooks that add listeners
// should have cleanup to remove them
return unlisten
}, [trackingId, listen])
}
Bu kancayı bir kez uygulamanızda, üste yakın bir yerde, ancak yine de bir yönlendiricinin içinde kullanmalısınız. App.js
Şuna benzer bir şeye sahibim :
App.js
import * as React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './Home/Home'
import About from './About/About'
// this is the file above
import { useTracking } from './useTracking'
export const App = () => {
useTracking('UA-USE-YOURS-HERE')
return (
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
)
}
// I find it handy to have a named export of the App
// and then the default export which wraps it with
// all the providers I need.
// Mostly for testing purposes, but in this case,
// it allows us to use the hook above,
// since you may only use it when inside a Router
export default () => (
<BrowserRouter>
<App />
</BrowserRouter>
)
Bir React tek sayfalı uygulamada yeni bir ekrana gittikten sonra ChromeVox ekran okuyucuyu "ekranın" üst kısmına odaklamaya çalışırken bu soruyla karşılaştım. Temel olarak, bu sayfanın sunucu tarafından oluşturulmuş yeni bir web sayfasına bir bağlantı izlenerek yüklenmesi durumunda ne olacağını taklit etmeye çalışmak.
Bu çözüm herhangi bir dinleyici gerektirmez, ChromeVox'u yeni bir url yoluna giderken istenen öğeye odaklamak için bir tıklamayı tetiklemek withRouter()
için componentDidUpdate()
yaşam döngüsü yöntemini kullanır .
Tüm uygulama ekranlarını içeren react-yönlendirici anahtar etiketinin etrafına sarılmış bir "Ekran" bileşeni oluşturdum.
<Screen>
<Switch>
... add <Route> for each screen here...
</Switch>
</Screen>
Screen.tsx
BileşenNot: Bu bileşen React + TypeScript kullanır
import React from 'react'
import { RouteComponentProps, withRouter } from 'react-router'
class Screen extends React.Component<RouteComponentProps> {
public screen = React.createRef<HTMLDivElement>()
public componentDidUpdate = (prevProps: RouteComponentProps) => {
if (this.props.location.pathname !== prevProps.location.pathname) {
// Hack: setTimeout delays click until end of current
// event loop to ensure new screen has mounted.
window.setTimeout(() => {
this.screen.current!.click()
}, 0)
}
}
public render() {
return <div ref={this.screen}>{this.props.children}</div>
}
}
export default withRouter(Screen)
Onun focus()
yerine kullanmayı denedim click()
, ancak tıklama ChromeVox'un şu anda okuduğu şeyi okumayı durdurmasına ve başlamasını söylediğim yerden yeniden başlamasına neden oluyor.
Gelişmiş not: Bu çözümde, <nav>
Ekran bileşeninin içinde bulunan ve <main>
içeriğin görsel olarak main
css kullanılarak konumlandırılmasının ardından oluşturulan gezinme order: -1;
. Yani sözde kodda:
<Screen style={{ display: 'flex' }}>
<main>
<nav style={{ order: -1 }}>
<Screen>
Bu çözümle ilgili herhangi bir düşünceniz, yorumunuz veya ipucunuz varsa, lütfen bir yorum ekleyin.
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Sidebar from './Sidebar';
import Chat from './Chat';
<Router>
<Sidebar />
<Switch>
<Route path="/rooms/:roomId" component={Chat}>
</Route>
</Switch>
</Router>
import { useHistory } from 'react-router-dom';
function SidebarChat(props) {
**const history = useHistory();**
var openChat = function (id) {
**//To navigate**
history.push("/rooms/" + id);
}
}
**//To Detect the navigation change or param change**
import { useParams } from 'react-router-dom';
function Chat(props) {
var { roomId } = useParams();
var roomId = props.match.params.roomId;
useEffect(() => {
//Detect the paramter change
}, [roomId])
useEffect(() => {
//Detect the location/url change
}, [location])
}