উত্তর:
আমি প্রপস 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/>এই
উপরের প্রসারিত করতে, আপনাকে ইতিহাসের বিষয়টিতে যেতে হবে। আপনি যদি ব্যবহার করে থাকেন তবে ইতিহাসের অবজেক্টের বৈশিষ্ট্য এবং ফাংশনগুলিতে প্রপসের মাধ্যমে অ্যাক্সেস পাওয়ার জন্য আপনি উচ্চতর অর্ডার উপাদান (HoC) দিয়ে আপনার উপাদানটি BrowserRouterআমদানি করতে withRouterএবং মোড়ানো করতে পারেন।
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 লাইব ব্যবহার করা উচিত ।
সেখান থেকে উদাহরণ
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.pushট্রিগার করে history.listen। ইতিহাসের v4 ডক্সে একটি বেস URL ব্যবহারের উদাহরণটি দেখুন । যেহেতু এটি আসলে কোনও ব্রাউজারের নেটিভ অবজেক্টের একটি মোড়ক, এটি নেটিভের মতো ঠিক আচরণ করে না। historyhistory
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]);
}
হুকস সহ
import { useHistory } from 'react-router-dom';
const Scroll = () => {
const history = useHistory();
useEffect(() => {
window.scrollTo(0, 0);
}, [history.location.pathname]);
return null;
}
প্রতিক্রিয়া হুক্স সহ, আমি ব্যবহার করছি 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আপনি যেমনটি চান ঠিক তেমন কাজ করে না, যেহেতু কলটি কেবল প্রথম রেন্ডারের পরে ট্রিগার হয়ে যায় তাই অযাচিত দেরি হয়।
আপনি যদি রিডেক্সের মতো কিছু রাজ্য ব্যবস্থাপক ব্যবহার করেন, সম্ভাবনা হ'ল স্টোরটিতে দীর্ঘকালীন অবস্থার কারণে আপনি পর্দায় একটি ফ্লিকার পাবেন।
আপনি সত্যিই যা চান তা হ'ল useLayoutEffectযেহেতু এটি তাত্ক্ষণিকভাবে ট্রিগার হয়ে যায়।
সুতরাং আমি একটি ছোট ইউটিলিটি ফাংশন লিখেছি যা আমি আমার রাউটারের মতো একই ডিরেক্টরিতে রেখেছি:
export const callApis = (fn, path) => {
useLayoutEffect(() => {
fn();
}, [path]);
};
যা আমি উপাদান এইচওসি এর মধ্যে থেকে এইভাবে কল করি:
callApis(() => getTopicById({topicId}), path);
pathঠেকনা পাস পরার যে matchবস্তু ব্যবহার করে যখন withRouter।
আমি ইতিহাসের পক্ষে ম্যানুয়ালি শোনার / প্রকাশ না করার পক্ষে নই। এটা ঠিক ইমো।