प्रोग्राम राउटर V4 का उपयोग करके प्रोग्रामेटिक रूप से नेविगेट करें


336

मैंने अभी react-routerv3 से v4 तक प्रतिस्थापित किया है।
लेकिन मुझे यकीन नहीं है कि कैसे एक के सदस्य समारोह में प्रोग्रामेटिक रूप से नेविगेट करने के लिए Component। यानी handleClick()फंक्शन में मैं /path/some/whereकुछ डेटा प्रोसेस करने के बाद नेविगेट करना चाहता हूं । मैं ऐसा करता था:

import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')

लेकिन मुझे v4 में ऐसे इंटरफेस नहीं मिले।
मैं v4 का उपयोग करके कैसे नेविगेट कर सकता हूं?


3
आप v4 के माध्यम से v4 में इतिहास वस्तु तक पहुँच सकते हैं:
this.props.history.push

6
क्या होगा अगर आप इसे एक अलग जगह से एक्सेस करना चाहते हैं Component? उदाहरण के लिए, Redux क्रियाओं के अंदर।
मैक्सिमस एस

73
कभी-कभी मैं सोचता हूं कि सिर्फ एक लिंक से दूसरे लिंक पर जाना इतना जटिल क्यों है)))
थाई ट्रान

12
कोई सोचता होगा कि इस दिन और उम्र पुनर्निर्देशन इतना जटिल नहीं होगा।
जॉन एलेन

मुझे यह पोस्ट मददगार
लगी

जवाबों:


414

यदि आप ब्राउज़र वातावरण को लक्षित कर रहे हैं, तो आपको react-router-domइसके बजाय पैकेज का उपयोग करने की आवश्यकता है react-router। वे उसी दृष्टिकोण का अनुसरण कर रहे हैं, जैसा कि कोर को अलग करने के लिए रिएक्ट ने किया था, ( react) और प्लेटफ़ॉर्म विशिष्ट कोड ( react-dom, react-native) सूक्ष्म अंतर के साथ, जिसे आपको दो अलग-अलग पैकेजों को स्थापित करने की आवश्यकता नहीं है, इसलिए पर्यावरण पैकेज में सब कुछ शामिल है आप की जरूरत है। आप इसे अपनी परियोजना में जोड़ सकते हैं:

yarn add react-router-dom

या

npm i react-router-dom

सबसे पहली बात जो आपको करने की ज़रूरत है वह यह है कि <BrowserRouter>आपके आवेदन में सबसे अधिक मूल घटक के रूप में प्रदान किया जाए । <BrowserRouter>HTML5 historyAPI का उपयोग करता है और इसे आपके लिए प्रबंधित करता है, इसलिए आपको इसे स्वयं इंस्टेंट करने और <BrowserRouter>एक घटक के रूप में इसे पास करने के बारे में चिंता करने की ज़रूरत नहीं है (जैसा कि आपको पिछले संस्करणों में करने की आवश्यकता थी)।

V4 में, प्रोग्रामेटिक रूप से नेविगेट करने के लिए, आपको historyऑब्जेक्ट को एक्सेस करने की आवश्यकता होती है , जो कि रिएक्ट के माध्यम से उपलब्ध है context, जब तक कि आपके पास अपने आवेदन में शीर्ष सबसे माता-पिता के रूप में एक <BrowserRouter> प्रदाता घटक है। पुस्तकालय संदर्भ के माध्यम से routerवस्तु को उजागर करता है , जो स्वयं historyएक संपत्ति के रूप में समाहित करता है। historyइंटरफेस जैसे कई नेविगेशन तरीकों, प्रदान करता है push, replaceऔर goBackदूसरों के बीच में,। आप गुणों और विधियों की पूरी सूची यहां देख सकते हैं

Redux / Mobx उपयोगकर्ताओं के लिए महत्वपूर्ण नोट

यदि आप अपने आवेदन में अपने राज्य प्रबंधन पुस्तकालय के रूप में redux या mobx का उपयोग कर रहे हैं, तो आप उन घटकों के साथ समस्याएँ ले सकते हैं, जिन्हें स्थान-पता होना चाहिए, लेकिन URL अपडेट ट्रिगर करने के बाद पुन: रेंडर नहीं किए गए हैं

ऐसा इसलिए हो रहा है क्योंकि संदर्भ मॉडल का उपयोग कर घटकों को react-routerपास locationकिया जाता है।

कनेक्ट और ऑब्जर्वर दोनों ऐसे कंपोनेंट बनाते हैं जिनके कंधों पर यूट्यूड के तरीके उनके करंट प्रॉप्स और उनके प्रॉप्स की तुलना में उथले तुलना करते हैं। कम से कम एक प्रोप बदल गया है, जब वे घटक केवल फिर से प्रस्तुत करना होगा। इसका मतलब यह है कि स्थान बदलने पर उन्हें अपडेट करने के लिए यह सुनिश्चित करने के लिए, उन्हें स्थान बदलने पर बदलने वाला एक प्रोप देने की आवश्यकता होगी।

इसे हल करने के लिए 2 दृष्टिकोण हैं:

  • अपने कनेक्टेड घटक को एक पथहीन में लपेटें <Route />। वर्तमान locationवस्तु एक सहारा है जो <Route>उस घटक को देता है जो इसे प्रस्तुत करता है
  • उच्च-क्रम वाले घटक के साथ अपने जुड़े घटक को लपेटें withRouter, वास्तव में एक ही प्रभाव होता है और locationएक प्रोप के रूप में इंजेक्शन होता है

यह निर्धारित करते हुए कि सिफारिश के अनुसार, प्रोग्राम को नेविगेट करने के चार तरीके हैं:

1.- एक <Route>घटक का उपयोग करना

यह एक घोषणात्मक शैली को बढ़ावा देता है। V4 से पहले, <Route />घटकों को आपके घटक पदानुक्रम के शीर्ष पर रखा गया था, जो आपके मार्गों की संरचना के बारे में पहले से सोच रहा था। हालाँकि, अब आपके पास अपने पेड़ में कहीं भी<Route> घटक हो सकते हैं , जिससे आपको URL के आधार पर सशर्त रूप से रेंडरिंग के लिए बेहतर नियंत्रण मिल सकता है। इंजेक्शन , और अपने घटक में सहारा के रूप में। नेविगेशन तरीकों (जैसे , , ...) के गुणों के रूप में उपलब्ध हैं वस्तु।RoutematchlocationhistorypushreplacegoBackhistory

या Routeतो component, renderया childrenरंगमंच की सामग्री का उपयोग करके कुछ के साथ प्रस्तुत करने के 3 तरीके हैं , लेकिन एक से अधिक का उपयोग न करें Route। चुनाव उपयोग के मामले पर निर्भर करता है, लेकिन मूल रूप से पहले दो विकल्प केवल आपके घटक को प्रस्तुत करेंगे यदि pathurl स्थान से मेल खाता है, जबकि childrenघटक के साथ प्रदान किया जाएगा कि पथ स्थान से मेल खाता है या नहीं (URL के आधार पर UI को समायोजित करने के लिए उपयोगी) मेल मिलाना)।

यदि आप अपने घटक रेंडरिंग आउटपुट को कस्टमाइज़ करना चाहते हैं , तो आपको अपने कंपोनेंट को किसी फ़ंक्शन में लपेटने और renderविकल्प का उपयोग करने की आवश्यकता है, ताकि आपके कंपोनेंट को पास करने के लिए match, locationऔर इसके अलावा आपकी इच्छा के किसी अन्य प्रॉपर को पास किया जा सके history। उदाहरण के लिए उदाहरण:

import { BrowserRouter as Router } from 'react-router-dom'

const ButtonToNavigate = ({ title, history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    {title}
  </button>
);

const SomeComponent = () => (
  <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)    

const App = () => (
  <Router>
    <SomeComponent /> // Notice how in v4 we can have any other component interleaved
    <AnotherComponent />
  </Router>
);

2.- withRouterHoC का उपयोग करना

यह उच्च क्रम घटक समान प्रॉप्स को इंजेक्ट करेगा Route। हालाँकि, यह सीमा को पार करता है कि आपके पास प्रति फ़ाइल केवल 1 HoC हो सकता है।

import { withRouter } from 'react-router-dom'

const ButtonToNavigate = ({ history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    Navigate
  </button>
);


ButtonToNavigate.propTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired,
  }),
};

export default withRouter(ButtonToNavigate);

3.- एक Redirectघटक का उपयोग करना

रेंडरिंग एक <Redirect>नए स्थान पर नेविगेट करेगा। लेकिन ध्यान रखें कि, डिफ़ॉल्ट रूप से , वर्तमान स्थान को सर्वर-रिडायरेक्ट्स (HTTP 3xx) की तरह नए से बदल दिया जाता है। नया स्थान toप्रोप द्वारा प्रदान किया गया है, जो एक स्ट्रिंग (URL को पुनर्निर्देशित करने के लिए) या एक locationवस्तु हो सकता है। यदि आप इसके बजाय इतिहास पर एक नई प्रविष्टि को आगे बढ़ाना चाहते हैं , तो एक pushप्रस्ताव भी पास करें और इसे सेट करेंtrue

<Redirect to="/your-new-location" push />

4.- routerसंदर्भ के माध्यम से मैन्युअल रूप से एक्सेस करना

थोड़ा हतोत्साहित क्योंकि संदर्भ अभी भी एक प्रयोगात्मक एपीआई है और यह प्रतिक्रिया के भविष्य के रिलीज में टूटने / बदलने की संभावना है

const ButtonToNavigate = (props, context) => (
  <button
    type="button"
    onClick={() => context.router.history.push('/my-new-location')}
  >
    Navigate to a new location
  </button>
);

ButtonToNavigate.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired,
  }),
};

कहने की आवश्यकता नहीं है कि अन्य राउटर घटक भी हैं जो गैर ब्राउज़र पारिस्थितिक तंत्र के लिए होते हैं, जैसे <NativeRouter>कि मेमोरी में नेविगेशन स्टैक की प्रतिकृति और react-router-nativeपैकेज के माध्यम से उपलब्ध रिएक्ट नेटिव प्लेटफॉर्म को लक्षित करता है ।

किसी भी अन्य संदर्भ के लिए, आधिकारिक डॉक्स पर एक नज़र डालने में संकोच न करें । पुस्तकालय के सह-लेखकों में से एक द्वारा बनाया गया एक वीडियो भी है जो प्रतिक्रिया-राउटर v4 के लिए एक अच्छा शांत परिचय प्रदान करता है, जिसमें कुछ बड़े बदलावों पर प्रकाश डाला गया है।


2
मैं V4 का उपयोग कर रहा हूं और उपरोक्त ठीक काम करता है। मैंने वी 4 राउटर के साथ कुछ समय व्यतीत करने का एक अच्छा समय बिताया है क्योंकि कुछ अजीब विकल्प हैं लेकिन उपरोक्त निश्चित रूप से काम करता है। मैं तुम्हें आयात कर रहे हैं मान withRouterसेreact-router-dom
सैम Parmenter

3
मैं withRouterसे आयात कर रहा हूँ react-router-dom<Route>
History.push

1
@rauliyohmc मैं इस बारे में गलत था। समस्या यह है कि मेरे पास <Router> एक रिएक्ट घटक है @observer, जिसे सजाया गया है , जो इस मुद्दे को चलाता है । इस @withRouterतरह के हर रिएक्ट कंपोनेंट पर काम करना है ।
ब्रेकडीएस

3
उन लोगों के लिए जो इस महान जवाब में आते हैं, withRouterबस एक एचओसी है Routeजो हुड के नीचे का उपयोग करता है । जिसका अर्थ है कि यह केवल 3 सहारा, इतिहास, मैच और स्थान का उपयोग करता है । ऊपर दिए गए उदाहरण में ऐसा प्रतीत होता है कि pushयह एक ऐसा प्रोप है जो withRouterइससे जुड़ जाएगा ButtonToNavigate, लेकिन ऐसा नहीं है। props.history.pushइसके बदले उपयोग करना होगा। आशा है कि यह उन लोगों की मदद करता है जो थोड़े भ्रमित थे।
२१

39
वाह। browserHistory.push('/path/some/where')बस बहुत सरल लगता है। लेखक अनिवार्य प्रोग्रामिंग को हतोत्साहित करने की कोशिश कर रहे हैं, लेकिन कभी-कभी यह सिर्फ बेहतर काम करता है!
लक्स

149

इसे करने का सबसे आसान तरीका:

this.props.history.push("/new/url")

ध्यान दें:

  • आप history propपैरेंट कंपोनेंट से उस कंपोनेंट को पास करना चाहते हैं, जिस एक्शन को आप उपलब्ध नहीं कराना चाहते हैं।

10
मैं 4.0 राउटर का उपयोग करता हूं, लेकिन प्रॉप्स पर कोई इतिहास की नहीं है। मेरे द्वारा यह कैसे किया जा सकता है?
निकोलस S.Xu

41
यदि आपके पास this.props.historyआपके घटक में उपलब्ध नहीं है तो आप कर सकते हैं import {withRouter} from 'react-router-dom'और फिर export default withRouter(MyComponent)(या const MyComponent = withRouter(...)) और यह historyआपके घटक के प्रॉपर में आइटम को सम्मिलित करेगा ।
मालविनस

@Malvineous दिलचस्प है, इस बारे में पता नहीं था! कोशिश करूँगा!
जिक्कू जोस

2
मुझे मूलभूत रूप से कुछ याद आ रहा है, क्योंकि यह मेरे लिए बहुत अच्छा काम करता है इसलिए मुझे नहीं पता कि सभी उत्तरों के लिए इतनी लंबी स्पष्टीकरण की आवश्यकता क्यों है।
जोशुआ पिंटर

history.pushहम पर क्लिक करते समय घटक रीमाउंट को कैसे रोकें और अपडेट को ट्रिगर कैसे करें<Link>
राहुल यादव

55

जब मैं रिएक्ट-राउटर v4 पर माइग्रेट कर रहा था तो मेरे पास एक समान मुद्दा था, इसलिए मैं नीचे अपना समाधान समझाने की कोशिश करूंगा।

कृपया इस उत्तर को समस्या को हल करने के सही तरीके के रूप में न मानें, मुझे लगता है कि एक अच्छा मौका है जिससे कुछ बेहतर होगा क्योंकि रिएक्टर राउटर v4 अधिक परिपक्व हो जाता है और बीटा को छोड़ देता है (यह पहले से ही मौजूद है और मुझे अभी पता नहीं चला) ।

संदर्भ के लिए, मुझे यह समस्या थी क्योंकि मैं कभी-कभार Redux-Sagaप्रोग्राम ऑब्जेक्ट को बदलने के लिए उपयोग करता हूं (कहते हैं कि जब कोई उपयोगकर्ता सफलतापूर्वक प्रमाणित होता है)।

रिएक्ट राउटर डॉक्स में, <Router> घटक पर एक नज़र डालें और आप देख सकते हैं कि आपके पास एक प्रोप के माध्यम से अपना स्वयं का इतिहास ऑब्जेक्ट पास करने की क्षमता है। यह समाधान का सार है - हम इतिहास वस्तु की आपूर्ति करने के लिए React-Routerएक से वैश्विक मॉड्यूल।

कदम:

  1. इतिहास npm मॉड्यूल स्थापित करें - yarn add history या npm install history --save
  2. history.jsअपने App.jsस्तर के फ़ोल्डर में एक फ़ाइल बनाएं (यह मेरी प्राथमिकता थी)

    // src/history.js
    
    import createHistory from 'history/createBrowserHistory';
    export default createHistory();`
  3. इस इतिहास वस्तु को अपने राउटर घटक में इस तरह जोड़ें

    // src/App.js
    
    import history from '../your/path/to/history.js;'
    <Router history={history}>
    // Route tags here
    </Router>
  4. अपना वैश्विक इतिहास ऑब्जेक्ट आयात करके पहले की तरह URL समायोजित करें :

    import history from '../your/path/to/history.js;'
    history.push('new/path/here/');

सब कुछ अब सिंक किया जाना चाहिए, और आपके पास प्रोग्राम ऑब्जेक्ट को इतिहास के रूप में स्थापित करने के एक तरीके तक पहुंच है और घटक / कंटेनर के माध्यम से नहीं।


5
इस परिवर्तन ने मेरे लिए काम किया, लेकिन केवल इसलिए कि मैं एक घटक के बाहर नेविगेट कर रहा हूं। अगर मैं ओपी जैसे एक घटक के अंदर नेविगेट कर रहा था, तो मैं Routeघटक द्वारा नीचे दिए गए प्रॉपर का उपयोग करके @rauliyohmc द्वारा सुझाए गए दृष्टिकोण का उपयोग करूंगा ।
डैन एलिस

2
यह 08/17 के रूप में अनुशंसित दृष्टिकोण है
Sp '

2
@ मेरे मामले में, अगर मैं इस तरह के दृष्टिकोण का उपयोग करता हूं, तो लिंक को पुश के बाद ठीक से अपडेट किया जाएगा, लेकिन घटकों को ठीक से प्रस्तुत नहीं किया जाता है (जैसे, लिंक को अपडेट करने के बाद, घटक तब तक अपडेट नहीं किया जाता है जब तक आप पृष्ठ ताज़ा नहीं करते हैं)। आपने कहां पाया कि यह अनुशंसित दृष्टिकोण है? कोई लिंक / स्रोत?
शांत

2
@ScCoCoates मैंने ऊपर दिए गए उदाहरण का उपयोग करके वास्तव में इतिहास को एक पैरामीटर के रूप में प्रदान करके हल किया, लेकिन बाद में मैंने स्वयं द्वारा नोड मॉड्यूल का डीबग किया। "BrowserHistory के रूप में रूटर" के आयात का उपयोग करते हुए, वेब के चारों ओर एक आम गलती हुई है, जब इसके बजाय प्रतिक्रिया-राउटर-डोम के नवीनतम संस्करण में राउटर नामक एक अन्य वस्तु है। उपरोक्त उदाहरण में बनाए गए इतिहास के साथ संयोजन का उपयोग करना ठीक काम करता है।
शांत

2
url अपडेट किया गया है, लेकिन पेज नई रूट के आधार पर रेंडर नहीं है। कोई भी समाधान? ट्रिगर मार्ग इतना कठिन क्यों है? जो लोग अभिक्रिया करते हैं, उनके दिमाग से बाहर है?
निकोलस S.Xu

43

टी एल; डॉ:

if (navigate) {
  return <Redirect to="/" push={true} />
}

सरल और घोषणात्मक उत्तर यह है कि आपको <Redirect to={URL} push={boolean} />संयोजन में उपयोग करने की आवश्यकता हैsetState()

पुश: बूलियन - जब सही होता है, तो पुनर्निर्देशन वर्तमान को बदलने के बजाय इतिहास पर एक नई प्रविष्टि को आगे बढ़ाएगा।


import { Redirect } from 'react-router'

class FooBar extends React.Component {
  state = {
    navigate: false
  }

  render() {
    const { navigate } = this.state

    // here is the important part
    if (navigate) {
      return <Redirect to="/" push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

पूरा उदाहरण यहां । और अधिक पढ़ें यहाँ

पुनश्च। उदाहरण स्थिति को इनिशियलाइज़ करने के लिए ES7 + प्रॉपर्टी इनिशियलाइज़र का उपयोग करता है । देखो यहाँ के रूप में अच्छी तरह से, अगर आप रुचि रखते हैं।


5
इसका उत्तर स्वीकार किया जाना चाहिए। सरलतम सुरुचिपूर्ण समाधान! +1 @ @ लोस्तॉयकोव के लिए
अली अब्बास

1
मैं भी घटक पर वापस नेविगेट करने के लिए सेट कर देता हूं क्योंकि मेरा बटन हेडर में है और अन्यथा केवल एक बार ही नेविगेट होगा।
पेटोरियम

यह तभी काम करता है जब आप पेज लोड होने पर रीडायरेक्ट के बारे में जानते हैं। यदि आप एक अतुल्यकालिक कॉल के लौटने की प्रतीक्षा कर रहे हैं (यानी Google या कुछ के साथ प्रमाणीकरण) तो आपको इनमें से एक history.push()विधि का उपयोग करना होगा ।
ब्रिटोहालोरन

वास्तव में नहीं, आप अभी भी <redirect /> घटक के साथ संयुक्त प्रतिक्रिया की घोषणात्मक प्रकृति का लाभ उठा सकते हैं। यदि पृष्ठ लोड नहीं होता है, तो आप
Lyubomir

@brittohalloran उचित प्रतिक्रिया राउटर का उपयोग करते हुए इस पद्धति का विचार है, सुनिश्चित करें कि आप फिर से प्रस्तुत करने के लिए मजबूर करने के लिए setState का उपयोग करते हैं।
कोई विशेष

16

useHistoryयदि आप फ़ंक्शन घटकों का उपयोग कर रहे हैं, तो हुक का उपयोग करें

आप उदाहरण useHistoryप्राप्त करने के लिए हुक का उपयोग कर सकते हैं history

import { useHistory } from "react-router-dom";

const MyComponent = () => {
  var history = useHistory();

  return (
    <button onClick={() => history.push("/about")}>
      Click me
    </button>
  );
}

useHistoryहुक आप इतिहास उदाहरण के लिए पहुँच है कि आप नेविगेट करने के लिए उपयोग कर सकते हैं देता है।

historyपृष्ठ घटकों के अंदर गुण का उपयोग करें

रिएक्ट राउटर historyपृष्ठ के घटकों सहित कुछ गुणों को इंजेक्ट करता है।

class HomePage extends React.Component {
  render() {
    const { history } = this.props;

    return (
      <div>
        <button onClick={() => history.push("/projects")}>
          Projects
        </button>
      </div>
    );
  }
}

withRouterराउटर गुणों को इंजेक्ट करने के लिए बाल घटकों को लपेटें

withRouterरैपर घटकों को राउटर गुण इंजेक्ट करता है। उदाहरण के लिए, आप इस रैपर का उपयोग राउटर को लॉगआउट बटन घटक को उपयोगकर्ता मेनू के अंदर रखने के लिए कर सकते हैं।

import { withRouter } from "react-router";

const LogoutButton = withRouter(({ history }) => {
  return (
    <button onClick={() => history.push("/login")}>
      Logout
    </button>
  );
});

export default LogoutButton;

11

आप इतिहास वस्तु तक पहुंचने के लिए बस प्रॉप्स का उपयोग कर सकते हैं: this.props.history.push('new_url')


5
केवल तब उपयोगी होता है जब घटक सीधे राउटर से नीचे आता है। ऐसा न हो कि आप इतिहास के हर उस घटक को पास करें जिसमें आपको इस कार्यक्षमता की आवश्यकता है।
mwieczorek

3
यदि आपके पास this.props.historyआपके घटक में उपलब्ध नहीं है तो आप कर सकते हैं import {withRouter} from 'react-router-dom'और फिर export default withRouter(MyComponent)(या const MyComponent = withRouter(...)) और यह historyआपके घटक के प्रॉपर में आइटम को सम्मिलित करेगा ।
मालविनस

9

चरण 1: शीर्ष पर आयात करने के लिए केवल एक चीज है:

import {Route} from 'react-router-dom';

चरण 2: अपने रूट में, इतिहास पास करें:

<Route
  exact
  path='/posts/add'
  render={({history}) => (
    <PostAdd history={history} />
  )}
/>

चरण 3: इतिहास अगले घटक में सहारा के भाग के रूप में स्वीकार किया जाता है, इसलिए आप बस यह कर सकते हैं:

this.props.history.push('/');

यह आसान और वास्तव में शक्तिशाली था।


7

यह काम:

import { withRouter } from 'react-router-dom';

const SomeComponent = withRouter(({ history }) => (
    <div onClick={() => history.push('/path/some/where')}>
        some clickable element
    </div>); 
);

export default SomeComponent;

5

मेरा जवाब एलेक्स के समान है । मुझे यकीन नहीं है कि क्यों रिएक्ट-राउटर ने इसे इतनी अनावश्यक रूप से जटिल बना दिया है। मुझे अनिवार्य रूप से वैश्विक होने की पहुंच पाने के लिए अपने घटक को एक एचओसी के साथ क्यों लपेटना चाहिए?

वैसे भी, यदि आप एक नज़र डालते हैं कि उन्होंने कैसे लागू किया <BrowserRouter>, तो यह इतिहास के चारों ओर एक छोटा आवरण है

हम उस इतिहास को थोड़ा बाहर खींच सकते हैं ताकि हम उसे कहीं से भी आयात कर सकें। हालाँकि, ट्रिक यह है कि यदि आप सर्वर-साइड रेंडरिंग कर रहे हैं और आप importइतिहास मॉड्यूल की कोशिश करते हैं , तो यह काम नहीं करेगा क्योंकि यह ब्राउज़र-केवल एपीआई का उपयोग करता है। लेकिन यह ठीक है क्योंकि हम आम तौर पर केवल एक क्लिक या किसी अन्य क्लाइंट-साइड ईवेंट के जवाब में रीडायरेक्ट करते हैं। इस प्रकार यह नकली है शायद यह ठीक है:

// history.js
if(__SERVER__) {
    module.exports = {};
} else {
    module.exports = require('history').createBrowserHistory();
}

वेबपैक की मदद से हम कुछ वेरिएशन को परिभाषित कर सकते हैं ताकि हम जान सकें कि हम किस माहौल में हैं:

plugins: [
    new DefinePlugin({
        '__SERVER__': 'false',
        '__BROWSER__': 'true', // you really only need one of these, but I like to have both
    }),

और अब आप कर सकते हैं

import history from './history';

कहीं से भी। यह सर्वर पर एक खाली मॉड्यूल लौटाएगा।

यदि आप इन मैजिक वर्सेस का उपयोग नहीं करना चाहते हैं, तो आपको बस requireवैश्विक ऑब्जेक्ट में जहां इसकी आवश्यकता है (आपके ईवेंट हैंडलर के अंदर) होगा। importकाम नहीं करेगा क्योंकि यह केवल शीर्ष स्तर पर काम करता है।


6
लानत है उन्होंने इसे इतना जटिल बना दिया।
अभिषेक

4
मैं आपसे पूरी तरह सहमत हूं। यह सिर्फ एक नेविगेशन के लिए बहुत जटिल है
थाई ट्रान

5

मुझे लगता है कि @rgommezz सबसे अधिक मामलों को घटाता है जिसमें मुझे लगता है कि यह काफी महत्वपूर्ण है।

// history is already a dependency or React Router, but if don't have it then try npm install save-dev history

import createHistory from "history/createBrowserHistory"

// in your function then call add the below 
const history = createHistory();
// Use push, replace, and go to navigate around.
history.push("/home");

यह मुझे उन कार्यों / कॉलों के साथ एक सरल सेवा लिखने की अनुमति देता है जिन्हें मैं अपने घटकों पर बहुत सारे HoC किए बिना किसी भी घटक से नेविगेशन करने के लिए कॉल कर सकता हूं ...

यह स्पष्ट नहीं है कि किसी ने इससे पहले समाधान क्यों नहीं दिया है। मुझे आशा है कि यह मदद करता है, और यदि आप इसके साथ कोई समस्या देखते हैं तो कृपया मुझे बताएं।


4

मैं कुछ दिनों के लिए v4 का परीक्षण कर रहा हूं और अब तक इसे पसंद कर रहा हूं! यह बस थोड़ी देर के बाद समझ में आता है।

मेरे पास भी यही सवाल था और मैंने पाया कि इसे काम करना सबसे अच्छा काम कर रहा है (और यह भी हो सकता है कि यह कैसे हो)। यह राज्य, एक टर्नरी ऑपरेटर और का उपयोग करता है <Redirect>

कंस्ट्रक्टर () में

this.state = {
    redirectTo: null
} 
this.clickhandler = this.clickhandler.bind(this);

प्रस्तुत करना () में

render(){
    return (
        <div>
        { this.state.redirectTo ?
            <Redirect to={{ pathname: this.state.redirectTo }} /> : 
            (
             <div>
               ..
             <button onClick={ this.clickhandler } />
              ..
             </div>
             )
         }

क्लिकहैंडलर में ()

 this.setState({ redirectTo: '/path/some/where' });

आशा है ये मदद करेगा। मुझे बताएं।


क्या इस विधि के साथ कोई नुकसान है? मेरे प्रोजेक्ट में केवल जब मैं कंस्ट्रक्टर में राज्य सेट करता हूं, तब से काम करता हूं, वहां से मैं अपने इच्छित किसी भी पृष्ठ पर रीडायरेक्ट कर सकता हूं। लेकिन जब मैंने ईवेंट पर राज्य सेट किया (उदाहरण के लिए प्रॉप्स बदल गया, उदाहरण के लिए) मुझे नए राज्य के साथ रेंडर करने की विधि दिखाई देती है, लेकिन रीडायरेक्ट नहीं होता है, मुझे एक ही पेज दिखाई देता है
दिमित्री मालुगिन

नुकसान यह है कि यह इतिहास को बदल देगा, इसलिए आप वापस हिट करने में सक्षम नहीं होंगे - इसलिए मूल रूप से, यह एक अच्छा समाधान नहीं है।
dannytenaglias 19

4

मैं कुछ समय के लिए इससे जूझता रहा - कुछ इतना सरल, फिर भी इतना जटिल, क्योंकि ReactJS वेब एप्लिकेशन लिखने का एक बिल्कुल अलग तरीका है, यह हमारे लिए बहुत पुराना है!

मैंने गड़बड़ को दूर करने के लिए एक अलग घटक बनाया:

// LinkButton.js

import React from "react";
import PropTypes from "prop-types";
import {Route} from 'react-router-dom';

export default class LinkButton extends React.Component {

    render() {
        return (
            <Route render={({history}) => (
                <button {...this.props}
                       onClick={() => {
                           history.push(this.props.to)
                       }}>
                    {this.props.children}
                </button>
            )}/>
        );
    }
}

LinkButton.propTypes = {
    to: PropTypes.string.isRequired
};

फिर इसे अपनी render()विधि में जोड़ें :

<LinkButton className="btn btn-primary" to="/location">
    Button Text
</LinkButton>

मुझे यह समाधान काफी उपयोगी लगता है। मैं कोड कॉपी कर रहा हूं। मुझे पता है कि आप इसे गीथूब पर डालते हैं - मैं इसे सीधे आपके लिए विशेषता दूँगा।
अभिनव मनचंदा

3

चूंकि इस भयानक डिजाइन से निपटने का कोई अन्य तरीका नहीं है, इसलिए मैंने एक सामान्य घटक लिखा जो withRouter HOC दृष्टिकोण का उपयोग करता है । नीचे दिया गया उदाहरण एक buttonतत्व को लपेट रहा है , लेकिन आप किसी भी क्लिक करने योग्य तत्व को बदल सकते हैं:

import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

const NavButton = (props) => (
  <Button onClick={() => props.history.push(props.to)}>
    {props.children}
  </Button>
);

NavButton.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func.isRequired
  }),
  to: PropTypes.string.isRequired
};

export default withRouter(NavButton);

उपयोग:

<NavButton to="/somewhere">Click me</NavButton>

3
this.props.history.push("/url")

यदि आपको यह नहीं मिला है। अपने घटक में उपलब्ध

import {withRouter} from 'react-router-dom'
export default withRouter(MyComponent)  

बहुत बहुत धन्यवाद!
QauseenMZ

1

जैसा कि कभी-कभी मैं अनुप्रयोग द्वारा फिर मार्गों को स्विच करना पसंद करता हूं, यह मेरे लिए काम करने का एक न्यूनतम उदाहरण है:

import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'

class App extends Component {
  constructor(props) {
    super(props)

    /** @type BrowserRouter */
    this.router = undefined
  }

  async handleSignFormSubmit() {
    await magic()
    this.router.history.push('/')
  }

  render() {
    return (
      <Router ref={ el => this.router = el }>
        <Link to="/signin">Sign in</Link>
        <Route path="/signin" exact={true} render={() => (
          <SignPage onFormSubmit={ this.handleSignFormSubmit } />
        )} />
      </Router>
    )
  }
}

0

आप में से उन लोगों के लिए जिन्हें किसी राउटर का उपयोग करने से पहले पूरी तरह से रिडायरेक्ट करने की आवश्यकता होती है React Routerया React Router Domआप केवल हिस्ट्री ऑब्जेक्ट पर आरोप लगाकर और अपने कंस्ट्रक्टर के भीतर उस पर एक नया स्टेट पुश करके रीडायरेक्ट प्रदान कर सकते हैं app.js। निम्नलिखित को धयान मे रखते हुए:

function getSubdomain(hostname) {
    let regexParse = new RegExp('[a-z\-0-9]{2,63}\.[a-z\.]{2,5}$');
    let urlParts = regexParse.exec(hostname);
    return hostname.replace(urlParts[0], '').slice(0, -1);
}

class App extends Component {

    constructor(props) {
        super(props);


        this.state = {
            hostState: true
        };

        if (getSubdomain(window.location.hostname).length > 0) {
            this.state.hostState = false;
            window.history.pushState('', '', './login');
        } else {
            console.log(getSubdomain(window.location.hostname));
        }

    }


    render() {
        return (

            <BrowserRouter>
                {this.state.hostState ? (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                        <Route path="/" component={PublicContainer}/>
                    </div>
                ) : (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                    </div>
                )

                }
            </BrowserRouter>)
    }


}

यहां हम एक उपडोमेन पर निर्भर आउटपुट रूट्स को बदलना चाहते हैं, घटक रेंडर से पहले इतिहास ऑब्जेक्ट के साथ बातचीत करके हम अपने मार्गों को छोड़ते हुए प्रभावी ढंग से रीडायरेक्ट कर सकते हैं।

window.history.pushState('', '', './login');
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.