मुझे ब्राउज़िंग इतिहास के आधार पर कुछ व्यावसायिक तर्क लागू करने होंगे।
मैं ऐसा कुछ करना चाहता हूं:
reactRouter.onUrlChange(url => {
this.history.push(url);
});
क्या URL अपडेट होने पर प्रतिक्रिया-राउटर से कॉलबैक प्राप्त करने का कोई तरीका है?
मुझे ब्राउज़िंग इतिहास के आधार पर कुछ व्यावसायिक तर्क लागू करने होंगे।
मैं ऐसा कुछ करना चाहता हूं:
reactRouter.onUrlChange(url => {
this.history.push(url);
});
क्या URL अपडेट होने पर प्रतिक्रिया-राउटर से कॉलबैक प्राप्त करने का कोई तरीका है?
जवाबों:
history.listen()
मार्ग परिवर्तन का पता लगाने का प्रयास करते समय आप फ़ंक्शन का उपयोग कर सकते हैं। ध्यान में रखते हुए कि आप उपयोग कर रहे हैं react-router v4
, अपने घटक को withRouter
HOC के साथ लपेटें ताकि history
प्रोप का उपयोग हो सके ।
history.listen()
एक unlisten
फ़ंक्शन देता है। आप इसे unregister
सुनने से उपयोग करेंगे ।
आप अपने मार्गों को जैसे कॉन्फ़िगर कर सकते हैं
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
और फिर AppContainer.js में
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);
इतिहास डॉक्स से :
आप वर्तमान स्थान में परिवर्तन का उपयोग करके सुन सकते हैं
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}`) })
स्थान ऑब्जेक्ट सहित window.location इंटरफ़ेस का एक सबसेट लागू करता है:
**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment
स्थानों में निम्नलिखित गुण भी हो सकते हैं:
location.state - इस स्थान के लिए कुछ अतिरिक्त स्थिति जो URL में नहीं रहती है (समर्थित (
createBrowserHistory
औरcreateMemoryHistory
)
location.key
- एक अद्वितीय इस स्थान का प्रतिनिधित्व स्ट्रिंग (में समर्थितcreateBrowserHistory
औरcreateMemoryHistory
)क्रिया
PUSH, REPLACE, or POP
इस बात पर निर्भर करती है कि उपयोगकर्ता को वर्तमान URL पर कैसे मिला।
जब आप प्रतिक्रिया-राउटर v3 का उपयोग कर रहे हैं, तो आप पैकेज history.listen()
से उपयोग कर सकते हैं history
जैसा कि ऊपर उल्लेख किया गया है या आप उपयोग भी कर सकते हैंbrowserHistory.listen()
आप अपने मार्गों को कॉन्फ़िगर और उपयोग कर सकते हैं जैसे
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()
बाद आप इसका उपयोग क्यों करेंगे withRouter
? आप का एक सरल तुलना कर सकता है nextProps.location.href === this.props.location.href
में componentWillUpdate
कुछ भी आप अगर यह बदल गया है क्या करने की जरूरत करने के लिए।
रिएक्टर राउटर 5.1 के लिए अपडेट।
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
विश्व स्तर पर ऑब्जेक्ट सुनना चाहते हैं , तो आपको इसे स्वयं बनाना होगा और इसे पास करना होगा Router
। तो आप इसे इसकी listen()
विधि के साथ सुन सकते हैं :
// 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>
इससे भी बेहतर अगर आप एक मॉड्यूल के रूप में इतिहास ऑब्जेक्ट बनाते हैं, तो आप इसे आसानी से आयात कर सकते हैं कहीं भी आपको इसकी आवश्यकता हो सकती है (जैसे import history from './history';
react-router v6
आगामी v6 में , इसे useLocation
और useEffect
हुक के संयोजन से किया जा सकता है
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])
...
}
सुविधाजनक पुन: उपयोग के लिए, आप इसे कस्टम useLocationChange
हुक में कर सकते हैं
// 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)
})
...
}
यदि आपको परिवर्तन पर पिछले मार्ग को देखने की आवश्यकता है, तो आप usePrevious
हुक के साथ संयोजन कर सकते हैं
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)
})
...
}
यह ध्यान रखना महत्वपूर्ण है कि पहले क्लाइंट मार्ग पर उपरोक्त सभी आग , साथ ही बाद में परिवर्तन। यदि यह समस्या है, तो बाद के उदाहरण का उपयोग करें और जांचें कि prevLocation
कुछ भी करने से पहले मौजूद है।
location
यहाँ स्पष्ट करने के लिए ब्राउज़र स्थान है, इसलिए यह हर घटक में समान है और हमेशा इस अर्थ में सही है। यदि आप अलग-अलग घटकों में हुक का उपयोग करते हैं, तो स्थान बदलने पर वे सभी समान मान प्राप्त करेंगे। मुझे लगता है कि वे उस जानकारी के साथ क्या करते हैं वह अलग होगा, लेकिन यह हमेशा सुसंगत है।
यह एक पुराना प्रश्न है और मैं मार्ग परिवर्तन के लिए मार्ग परिवर्तन के लिए सुनने की व्यावसायिक आवश्यकता को नहीं समझता; गोल चक्कर लगता है।
लेकिन अगर आप यहाँ समाप्त हो गए हैं क्योंकि आप सभी चाहते थे कि 'page_path'
गूगल एनालिटिक्स / ग्लोबल साइट टैग / कुछ इसी तरह के रिएक्शन-राउटर रूट में बदलाव किया जाए, तो यहां एक हुक का उपयोग किया जा सकता है। मैंने इसे स्वीकृत उत्तर के आधार पर लिखा है:
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])
}
आपको अपने ऐप में एक बार इस हुक का उपयोग करना चाहिए , कहीं शीर्ष के पास लेकिन फिर भी एक राउटर के अंदर। मैं इसे App.js
इस तरह दिखता है:
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>
)
मुझे इस सवाल का सामना करना पड़ा क्योंकि मैं रिएक्ट सिंगल पेज ऐप में एक नई स्क्रीन पर नेविगेट करने के बाद "स्क्रीन" के शीर्ष पर ChromeVox स्क्रीन रीडर को फोकस करने का प्रयास कर रहा था। मूल रूप से यह अनुकरण करने की कोशिश की जा रही है कि क्या होगा यदि इस पेज को एक नए सर्वर द्वारा प्रदान किए गए वेब पेज के लिंक के द्वारा लोड किया गया था।
यह समाधान किसी भी श्रोताओं की आवश्यकता नहीं है, इसे इस्तेमाल करता है withRouter()
और componentDidUpdate()
जीवन चक्र विधि जब एक नया url पथ पर नेविगेट करके वांछित तत्व पर ChromeVox ध्यान केंद्रित करने के लिए एक क्लिक गति प्रदान करने के।
मैंने एक "स्क्रीन" घटक बनाया जो प्रतिक्रिया-राउटर स्विच टैग के चारों ओर लिपटा हुआ है जिसमें सभी ऐप्स स्क्रीन हैं।
<Screen>
<Switch>
... add <Route> for each screen here...
</Switch>
</Screen>
Screen.tsx
अंगनोट: यह घटक React + TypeScript का उपयोग करता है
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)
मैंने focus()
इसके बजाय का उपयोग करने की कोशिश की थी click()
, लेकिन वर्तमान में जो कुछ भी पढ़ रहा है, उसे पढ़ना बंद कर दें और जहां मैं इसे शुरू करने के लिए कहूं, उसे पढ़ना बंद कर दें।
उन्नत नोट: इस समाधान में, नेविगेशन <nav>
जो कि स्क्रीन घटक के अंदर है और <main>
सामग्री के बाद प्रदान किया गया है, का main
उपयोग करते हुए सीएसएस के ऊपर स्थित है order: -1;
। इसलिए छद्म कोड में:
<Screen style={{ display: 'flex' }}>
<main>
<nav style={{ order: -1 }}>
<Screen>
यदि आपके पास इस समाधान के बारे में कोई विचार, टिप्पणी या सुझाव हैं, तो कृपया एक टिप्पणी जोड़ें।
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])
}