जवाबों:
मैं सहारा withRouter
पाने के लिए उपयोग करता हूं location
। जब घटक एक नए मार्ग के कारण अपडेट किया जाता है, तो मैं जाँचता हूं कि क्या मूल्य बदल गया है:
@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>
}
}
आशा करता हूँ की ये काम करेगा
withRouter
रहा हूं, लेकिन मुझे त्रुटि मिल रही है You should not use <Route> or withRouter() outside a <Router>
। मुझे <Router/>
उपरोक्त कोड में कोई घटक नहीं दिख रहा है । तो यह कैसे काम कर रहा है?
<Switch>
घटक डी-फैक्टो राउटर के रूप में काम कर रहा है। <Route>
मिलान पथ के लिए केवल पहली प्रविष्टि, प्रदान की जाएगी। <Router/>
इस परिदृश्य में किसी भी घटक की आवश्यकता नहीं है
उपरोक्त पर विस्तार करने के लिए, आपको इतिहास ऑब्जेक्ट पर प्राप्त करना होगा। यदि आप उपयोग कर रहे हैं 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);
केवल इस बात की जानकारी होनी चाहिए कि प्रॉप को अप्रोच करने के लिए विथ राउटर और अधिकांश अन्य तरीके हैं history
क्योंकि वे ऑब्जेक्ट को डी-स्ट्रक्चर करते हैं।
withRoutes
कर लो withRouter
।
आपको इतिहास 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}`)
})
const unlisten = history.listen(myListener); unlisten();
withRouter
, history.listen
और useEffect
(रिएक्ट हुक) एक साथ काफी अच्छी तरह से काम करता है:
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)
श्रोता कॉलबैक किसी भी समय एक मार्ग को बदल देगा, और वापसी history.listen
एक शटडाउन हैंडलर है जो अच्छी तरह से खेलता है useEffect
।
v5.1 उपयोगी हुक का परिचय देता है 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
:। आपको यह सुनिश्चित करने की आवश्यकता है कि यूटीलोकेशन () कॉल उसी घटक में नहीं है जो राउटर को पेड़ में डालता है: यहां देखें
हुक के साथ:
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>
घटक के रूप में प्रस्तुत करना
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]);
}
हुक के साथ
प्रतिक्रिया हुक्स के साथ, मैं उपयोग कर रहा हूं 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])
कुछ मामलों में आप इस तरह से 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
विधि में स्थिति बदलते हैं , तो यह 'अधिकतम अद्यतन गहराई से अधिक' त्रुटि का कारण हो सकता है।
useEffect
हुक के साथ श्रोता को जोड़े बिना मार्ग परिवर्तनों का पता लगाना संभव है।
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);
मैं अभी इस समस्या से निपटता हूं, इसलिए मैं दिए गए अन्य उत्तरों पर एक पूरक के रूप में अपना समाधान जोड़ूंगा।
यहाँ समस्या यह है कि useEffect
वास्तव में यह काम नहीं करता है जैसा कि आप इसे चाहते हैं, क्योंकि कॉल केवल पहले रेंडर के बाद चालू हो जाता है इसलिए अवांछित देरी होती है।
यदि आप कुछ राज्य प्रबंधक जैसे Redux का उपयोग करते हैं, तो संभावना है कि आपको स्टोर में स्थिति की स्थिति के कारण स्क्रीन पर एक फ़्लिकर मिलेगा।
क्या आप वास्तव में चाहते हैं का उपयोग करने के लिए है useLayoutEffect
क्योंकि यह तुरंत ट्रिगर हो जाता है।
इसलिए मैंने एक छोटी उपयोगिता फ़ंक्शन लिखा, जिसे मैंने अपने राउटर के समान निर्देशिका में रखा:
export const callApis = (fn, path) => {
useLayoutEffect(() => {
fn();
}, [path]);
};
जिसे मैं इस तरह घटक एचओसी के भीतर से कॉल करता हूं:
callApis(() => getTopicById({topicId}), path);
path
वह प्रोप है जो match
उपयोग करते समय ऑब्जेक्ट में पास हो जाता है withRouter
।
मैं वास्तव में इतिहास पर मैन्युअल रूप से सुनने / गैर-सूचीबद्ध होने के पक्ष में नहीं हूं। वह सिर्फ इमो है।