প্রতিক্রিয়া রাউটার ভি 4 এ রুট পরিবর্তনগুলি কীভাবে শুনবেন?


138

আমার কাছে কয়েকটি বাটন রয়েছে যা রুট হিসাবে কাজ করে। যতবারই রুটটি পরিবর্তন করা হয়, আমি নিশ্চিত করতে চাই যে সক্রিয় বাটনটি সক্রিয় রয়েছে।

প্রতিক্রিয়া রাউটার ভি 4 এর রুট পরিবর্তনগুলি শুনতে কি কোনও উপায় আছে?


উত্তর:


170

আমি প্রপস 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>
  }
}

আশা করি এটা সাহায্য করবে


21
বিক্রিয়া রাউটার ভি 4-তে 'this.plines.location.pathname' ব্যবহার করুন।
ptorsson

4
@ ব্লাডফিউশন আমি একই কাজ করছি এবং ব্যবহার withRouterকরছি তবে আমি ত্রুটি পাচ্ছি You should not use <Route> or withRouter() outside a <Router><Router/>উপরের কোডে আমি কোনও উপাদান দেখছি না । তাহলে এটি কীভাবে কাজ করছে?
ম্যাভেরিক

1
হাই @ ম্যাভারিক আপনার কোডটি কেমন দেখাচ্ছে তা আমি নিশ্চিত নই, তবে উপরের উদাহরণে <Switch>উপাদানটি ডি-ফ্যাক্টো রাউটার হিসাবে কাজ করছে। <Route>মিলে যাওয়ার পাথের জন্য কেবল প্রথম প্রবেশিকাটি রেন্ডার হবে। <Router/>এই
দৃশ্যে

1
@ উইথ রউটার ব্যবহার করতে আপনাকে এনপিএম ইনস্টল করতে হবে - সেভ-ডেভ ট্রান্সফর্ম-
ডেকোরটার

68

উপরের প্রসারিত করতে, আপনাকে ইতিহাসের বিষয়টিতে যেতে হবে। আপনি যদি ব্যবহার করে থাকেন তবে ইতিহাসের অবজেক্টের বৈশিষ্ট্য এবং ফাংশনগুলিতে প্রপসের মাধ্যমে অ্যাক্সেস পাওয়ার জন্য আপনি উচ্চতর অর্ডার উপাদান (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
সের্গে রিউতসকি

হ্যাঁ, দুঃখিত, এটি নির্দেশ করার জন্য ধন্যবাদ। আমি পোস্ট সংশোধন করেছি। আমি প্রশ্নের শীর্ষে সঠিক আমদানি রেখেছি এবং তারপরে কোড উদাহরণে এটি ভুল বানান।
স্যাম পারমেন্টার

5
আমি মনে করি উইথরউটারের বর্তমান সংস্করণটিhistory ভেরিয়েবলের চেয়ে পাস হয় listen
মাইকব্রিজ

5
বিব্রতকর প্রদর্শনের জন্য পোস্টটি সংশোধন করা ভাল হবে; এই কোডটিতে এটির একটি মেমরি ফুটো রয়েছে।
অ্যান্ড্রুসথপাউ

34

আপনার ইতিহাসের 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}`)
})

1
ইতিহাস.পুষস্টেট () এবং হিস্টোরি.রেপসস্টেট () কলগুলি পপস্টেট ইভেন্টটিকে ট্রিগার করে না, তাই এটি একাই সমস্ত রুটের পরিবর্তনগুলি কভার করবে না।
রায়ান

1
@ রায়ান মনে হয় এটি history.pushট্রিগার করে history.listenইতিহাসের v4 ডক্সে একটি বেস URL ব্যবহারের উদাহরণটি দেখুন । যেহেতু এটি আসলে কোনও ব্রাউজারের নেটিভ অবজেক্টের একটি মোড়ক, এটি নেটিভের মতো ঠিক আচরণ করে না। historyhistory
রকালাইটে

এটি একটি আরও ভাল সমাধানের মতো অনুভূত হয়, কারণ প্রায়শই আপনাকে ইভেন্ট পুশিংয়ের জন্য রুটের পরিবর্তনগুলি শুনতে হবে যা উপাদান লাইফাইসাইকেলের ইভেন্টগুলির সাথে সম্পর্কিত নয়।
ড্যানিয়েল দুবভস্কি

12
সম্ভাব্য স্মৃতি ফুটো! আপনি এটি করা খুব গুরুত্বপূর্ণ! "আপনি যখন ইতিহাস.লিস্টেন ব্যবহার করে কোনও শ্রোতার সংযুক্ত করেন, এটি শ্রোতাদের অপসারণ করতে ব্যবহার করা যেতে পারে এমন একটি ফাংশন ফিরিয়ে দেয়, যা পরে ক্লিনআপ যুক্তিতে যুক্ত করা যেতে পারে:const unlisten = history.listen(myListener); unlisten();
দেহান ডি ক্রোস

ইতিহাস প্যাকেজে নথিপত্রের জন্য এখানে যান। github.com/ReactTraining/history/blob/master/docs/…
জেসন কিম

25

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


13

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>
}

4
শুধু একটি নোট হিসাবে আমি একটি ত্রুটি নিয়ে সমস্যায় ছিল: Cannot read property 'location' of undefined at useLocation। আপনাকে নিশ্চিত করতে হবে যে ইউজলোকেশন () কলটি রাউটারটিকে গাছের মধ্যে রাখে একই উপাদানটিতে নেই: এখানে দেখুন
21

11

হুক সহ:

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>উপাদান হিসাবে আমদানি এবং রেন্ডার


11
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]);

}

হুকস সহ


হলি জেসিস! এটা কিভাবে কাজ করে? আপনার উত্তরটি দুর্দান্ত! buti মধ্যে ডিবাগার বিন্দু করা useEffect কিন্তু যে কোন সময় আমি পথনাম অবস্থান পরিবর্তন করেছে থাকুন undefined ? আপনি কোন ভাল নিবন্ধ শেয়ার করতে পারেন? কোনও পরিষ্কার তথ্য খুঁজে পাওয়া শক্ত কারণ
অ্যালেক্সনিকনভ

7
import { useHistory } from 'react-router-dom';

const Scroll = () => {
  const history = useHistory();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [history.location.pathname]);

  return null;
}

এটিও কি হ্যাশ পরিবর্তনগুলি দেখে? রুট / এ # 1 -> রুট / এ # 2
নেরেন

1

প্রতিক্রিয়া হুক্স সহ, আমি ব্যবহার করছি 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])

0

কিছু ক্ষেত্রে আপনি এর 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পদ্ধতিতে রাষ্ট্র পরিবর্তন করেন তবে এর ফলে 'সর্বোচ্চ আপডেটের গভীরতা অতিক্রম' হতে পারে।


0

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);

0

আমি কেবল এই সমস্যার সাথে মোকাবিলা করেছি, তাই আমি প্রদত্ত অন্যান্য উত্তরের পরিপূরক হিসাবে আমার সমাধান যুক্ত করব।

এখানে সমস্যাটি হ'ল এটি useEffectআপনি যেমনটি চান ঠিক তেমন কাজ করে না, যেহেতু কলটি কেবল প্রথম রেন্ডারের পরে ট্রিগার হয়ে যায় তাই অযাচিত দেরি হয়।
আপনি যদি রিডেক্সের মতো কিছু রাজ্য ব্যবস্থাপক ব্যবহার করেন, সম্ভাবনা হ'ল স্টোরটিতে দীর্ঘকালীন অবস্থার কারণে আপনি পর্দায় একটি ফ্লিকার পাবেন।

আপনি সত্যিই যা চান তা হ'ল useLayoutEffectযেহেতু এটি তাত্ক্ষণিকভাবে ট্রিগার হয়ে যায়।

সুতরাং আমি একটি ছোট ইউটিলিটি ফাংশন লিখেছি যা আমি আমার রাউটারের মতো একই ডিরেক্টরিতে রেখেছি:

export const callApis = (fn, path) => {
    useLayoutEffect(() => {
      fn();
    }, [path]);
};

যা আমি উপাদান এইচওসি এর মধ্যে থেকে এইভাবে কল করি:

callApis(() => getTopicById({topicId}), path);

pathঠেকনা পাস পরার যে matchবস্তু ব্যবহার করে যখন withRouter

আমি ইতিহাসের পক্ষে ম্যানুয়ালি শোনার / প্রকাশ না করার পক্ষে নই। এটা ঠিক ইমো।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.