प्रतिक्रिया रूटर v4 / v5 के साथ नेस्टेड मार्ग


261

मैं वर्तमान में प्रतिक्रिया रूटर v4 का उपयोग करते हुए नेस्टिंग मार्गों से संघर्ष कर रहा हूं।

निकटतम उदाहरण रिएक्ट-राउटर v4 प्रलेखन में मार्ग विन्यास था ।

मैं अपने ऐप को 2 अलग-अलग हिस्सों में विभाजित करना चाहता हूं।

एक दृश्यपटल और एक व्यवस्थापक क्षेत्र।

मैं कुछ इस तरह के बारे में सोच रहा था:

<Match pattern="/" component={Frontpage}>
  <Match pattern="/home" component={HomePage} />
  <Match pattern="/about" component={AboutPage} />
</Match>
<Match pattern="/admin" component={Backend}>
  <Match pattern="/home" component={Dashboard} />
  <Match pattern="/users" component={UserPage} />
</Match>
<Miss component={NotFoundPage} />

फ्रंटएंड में व्यवस्थापक क्षेत्र की तुलना में एक अलग लेआउट और शैली है। तो मुख पृष्ठ के भीतर घर मार्ग, के बारे में और इसलिए एक बच्चे के मार्ग होना चाहिए।

/ होम को फ्रंटपेज घटक में प्रस्तुत किया जाना चाहिए और / व्यवस्थापक / घर को बैकएंड घटक के भीतर प्रदान किया जाना चाहिए।

मैंने कुछ बदलावों की कोशिश की लेकिन मैं हमेशा मार / घर या / व्यवस्थापक / घर में नहीं समाप्त हुआ।

संपादित करें - 19.04.2017

क्योंकि इस पोस्ट में अभी बहुत सारे विचार हैं, मैंने इसे अंतिम समाधान के साथ अद्यतन किया। मुझे उम्मीद है कि यह किसी की मदद करता है।

संपादित करें - 08.05.2017

पुराने हल निकाले

अंतिम समाधान:

यह अंतिम समाधान है जिसका मैं अभी उपयोग कर रहा हूं। इस उदाहरण में पारंपरिक 404 पृष्ठ की तरह एक वैश्विक त्रुटि घटक भी है।

import React, { Component } from 'react';
import { Switch, Route, Redirect, Link } from 'react-router-dom';

const Home = () => <div><h1>Home</h1></div>;
const User = () => <div><h1>User</h1></div>;
const Error = () => <div><h1>Error</h1></div>

const Frontend = props => {
  console.log('Frontend');
  return (
    <div>
      <h2>Frontend</h2>
      <p><Link to="/">Root</Link></p>
      <p><Link to="/user">User</Link></p>
      <p><Link to="/admin">Backend</Link></p>
      <p><Link to="/the-route-is-swiggity-swoute">Swiggity swooty</Link></p>
      <Switch>
        <Route exact path='/' component={Home}/>
        <Route path='/user' component={User}/>
        <Redirect to={{
          state: { error: true }
        }} />
      </Switch>
      <footer>Bottom</footer>
    </div>
  );
}

const Backend = props => {
  console.log('Backend');
  return (
    <div>
      <h2>Backend</h2>
      <p><Link to="/admin">Root</Link></p>
      <p><Link to="/admin/user">User</Link></p>
      <p><Link to="/">Frontend</Link></p>
      <p><Link to="/admin/the-route-is-swiggity-swoute">Swiggity swooty</Link></p>
      <Switch>
        <Route exact path='/admin' component={Home}/>
        <Route path='/admin/user' component={User}/>
        <Redirect to={{
          state: { error: true }
        }} />
      </Switch>
      <footer>Bottom</footer>
    </div>
  );
}

class GlobalErrorSwitch extends Component {
  previousLocation = this.props.location

  componentWillUpdate(nextProps) {
    const { location } = this.props;

    if (nextProps.history.action !== 'POP'
      && (!location.state || !location.state.error)) {
        this.previousLocation = this.props.location
    };
  }

  render() {
    const { location } = this.props;
    const isError = !!(
      location.state &&
      location.state.error &&
      this.previousLocation !== location // not initial render
    )

    return (
      <div>
        {          
          isError
          ? <Route component={Error} />
          : <Switch location={isError ? this.previousLocation : location}>
              <Route path="/admin" component={Backend} />
              <Route path="/" component={Frontend} />
            </Switch>}
      </div>
    )
  }
}

class App extends Component {
  render() {
    return <Route component={GlobalErrorSwitch} />
  }
}

export default App;

1
अंतिम उत्तर के साथ अपने प्रश्न को अपडेट करने के लिए धन्यवाद! बस एक सुझाव: हो सकता है कि आप केवल 4 वीं सूची और पहले रख सकते हैं, क्योंकि दूसरे एपीआई के पुराने संस्करणों का उपयोग कर रहे हैं और उत्तर से विचलित कर रहे हैं
Giuliano Vilela

lol, मुझे नहीं पता कि यह दिनांक किस प्रारूप की है: 08.05.2017 मेरा सुझाव है कि यदि आप लोगों को भ्रमित नहीं करना चाहते हैं तो आप तारीखों के लिए सार्वभौमिक ISO8601 प्रारूप का उपयोग करें। 08 माह या दिन है? ISO8601 = year.month.day hour.minute.second (उत्तरोत्तर अधिक दानेदार)
wesm

अच्छा अद्यतन अंतिम समाधान है, लेकिन मुझे लगता है कि आपको previousLocationतर्क की आवश्यकता नहीं है।
tudorpavel

पूरी तरह से पुनर्लेखन प्रतिक्रिया के लिए प्रेरणा क्या है। यह बेहतर कारण है
ऑलिवर वाटकिंस

यह घोषणात्मक दृष्टिकोण है। इसलिए आप अपनी रूटिंग सेट कर सकते हैं क्योंकि आप प्रतिक्रिया घटकों का उपयोग करेंगे।
डेटोमल

जवाबों:


318

प्रतिक्रिया-राउटर- v4 में आप घोंसला नहीं बनाते हैं <Routes />। इसके बजाय, आप उन्हें दूसरे के अंदर डालते हैं <Component />


उदाहरण के लिए

<Route path='/topics' component={Topics}>
  <Route path='/topics/:topicId' component={Topic} />
</Route>

बन जाना चाहिए

<Route path='/topics' component={Topics} />

साथ में

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <Link to={`${match.url}/exampleTopicId`}>
      Example topic
    </Link>
    <Route path={`${match.path}/:topicId`} component={Topic}/>
  </div>
) 

यहाँ प्रतिक्रिया-राउटर प्रलेखन से सीधे एक मूल उदाहरण है


मैं मूल लिंक में आपके लिंक से लागू करने में सक्षम हूं, हालांकि जब मैं मैन्युअल रूप से यूआरएल टाइप करता हूं तो यह मेरे लोकलहोस्ट सर्वर पर काम नहीं करता है। लेकिन यह आपके उदाहरण पर है। जब मैं url मैनुअल को # के साथ लिखता हूं, तो दूसरे हैंडशॉर्टर ठीक से काम करता है। क्या आपको कुछ पता है कि मेरे लोकलहोस्ट सर्वर पर BrowserRouter काम क्यों नहीं कर रहा है जब मैं मैन्युअल रूप से url टाइप करता हूं?
himawan_r

8
क्या आप एक कक्षा में विषय घटक बना सकते हैं? और 'मैच' पैरामीटर कहाँ आया है? रेंडर में ()?
user1076813

21
हास्यास्पद लगता है आप सिर्फ निहित होने के to="exampleTopicId"साथ नहीं कर सकते ${match.url}
हरियालीवाला

8
आपके पास डॉक्स के प्रति नेस्टेड रूट रिएक्ट्रेनिंग . com/react-router/web/example/route-constig हो सकते हैं । यह डॉक्स में विषय के अनुसार केंद्रीकृत मार्ग विन्यास की अनुमति देगा। सोचें कि अनुपलब्ध होने पर किसी बड़ी परियोजना में प्रबंधन करना कितना मुश्किल होगा।
JustDave

5
ये नेस्टेड रूट नहीं हैं, यह रूट के रेंडर प्रॉपर्टी का उपयोग करते हुए अभी भी एक-स्तरीय रूटिंग है जो एक इनपुट के रूप में एक कार्यात्मक घटक लेता है, अधिक ध्यान से देखें, प्रतिक्रिया राउटर के अर्थ में कोई नेस्टिंग नहीं है। उन मार्गों की सूची जो पैटर्न मिलान का उपयोग करती है।
हुसोमिर

102

react-router v6

2020 के लिए एक अद्यतन: आगामी v6 रिलीज में नेस्टेड Routeघटक होंगे जो जस्ट वर्क ™ हैं। इस ब्लॉग पोस्ट में उदाहरण कोड देखें

जबकि मूल प्रश्न v4 / v5 के बारे में है , जब v6 जहाजों का सही उत्तर होगा कि यदि आप कर सकते हैं । यह वर्तमान में अल्फा में है।


react-router v4 & v5

यह सही है कि रूट के घोंसले के लिए आपको उन्हें रूट के चाइल्ड घटक में रखने की आवश्यकता है।

हालाँकि यदि आप अपने रूट्स को घटकों के ऊपर तोड़ने के बजाय अधिक इनलाइन सिंटैक्स पसंद करते हैं , तो आप renderजिस रूट के नीचे घोंसला बनाना चाहते हैं, उसके प्रोफ़ेशन के लिए एक कार्यात्मक घटक प्रदान कर सकते हैं ।

<BrowserRouter>

  <Route path="/" component={Frontpage} exact />
  <Route path="/home" component={HomePage} />
  <Route path="/about" component={AboutPage} />

  <Route
    path="/admin"
    render={({ match: { url } }) => (
      <>
        <Route path={`${url}/`} component={Backend} exact />
        <Route path={`${url}/home`} component={Dashboard} />
        <Route path={`${url}/users`} component={UserPage} />
      </>
    )}
  />

</BrowserRouter>

यदि आप रुचि रखते हैं कि renderप्रॉप का उपयोग क्यों किया जाना चाहिए, न कि componentप्रॉप, तो ऐसा इसलिए है क्योंकि यह इनलाइन फंक्शनल कंपोनेंट को हर रेंडर के रिमाउंट किए जाने से रोकता है। अधिक विवरण के लिए दस्तावेज़ देखें

ध्यान दें कि उदाहरण एक टुकड़े में नेस्टेड मार्गों को लपेटता है । रिएक्ट 16 से पहले, आप <div>इसके बजाय एक कंटेनर का उपयोग कर सकते हैं ।


16
ईश्वर का एकमात्र समाधान है कि यह स्पष्ट, अप्रस्तुत है और अपेक्षा के अनुरूप काम करता है। मेरी इच्छा है कि राउटर 3 नेस्टेड रूट वापस आए।
मेरुनास ग्रिंकसलिटिस

यह एक सही कोणीय मार्ग-आउटलेट जैसा दिखता है
पार्थ रंजन

4
आपको उपयोग करना चाहिए match.path, नहीं match.url। पूर्व आमतौर पर रूट pathप्रोप में उपयोग किया जाता है ; बाद में जब आप एक नया मार्ग (जैसे लिंक toप्रोप) धक्का देते हैं
nbkhope

50

इस प्रतिक्रिया को पोस्ट / उत्तर दिए जाने के बाद से केवल प्रतिक्रिया-राउटर v4 को मौलिक रूप से बदलना चाहते थे ।

और कोई <Match>घटक नहीं है! <Switch>यह सुनिश्चित करने के लिए कि केवल पहला मैच रेंडर किया गया है। <Redirect>अच्छी तरह से .. दूसरे मार्ग पर पुनः निर्देशित करता है। exactआंशिक मैच को या तो अंदर छोड़ दें या छोड़ दें ।

डॉक्स देखें। वे महान हैं। https://reacttraining.com/react-router/

यहाँ एक उदाहरण है मुझे आशा है कि आपके प्रश्न का उत्तर देने के लिए उपयोग करने योग्य है।

<Router>
  <div>
    <Redirect exact from='/' to='/front'/>
    <Route path="/" render={() => {
      return (
        <div>
          <h2>Home menu</h2>
          <Link to="/front">front</Link>
          <Link to="/back">back</Link>
        </div>
      );
    }} />          
    <Route path="/front" render={() => {
      return (
        <div>
        <h2>front menu</h2>
        <Link to="/front/help">help</Link>
        <Link to="/front/about">about</Link>
        </div>
      );
    }} />
    <Route exact path="/front/help" render={() => {
      return <h2>front help</h2>;
    }} />
    <Route exact path="/front/about" render={() => {
      return <h2>front about</h2>;
    }} />
    <Route path="/back" render={() => {
      return (
        <div>
        <h2>back menu</h2>
        <Link to="/back/help">help</Link>
        <Link to="/back/about">about</Link>
        </div>
      );
    }} />
    <Route exact path="/back/help" render={() => {
      return <h2>back help</h2>;
    }} />
    <Route exact path="/back/about" render={() => {
      return <h2>back about</h2>;
    }} />
  </div>
</Router>

उम्मीद है कि यह मदद की, मुझे पता है। यदि यह उदाहरण आपके प्रश्न का पर्याप्त उत्तर नहीं दे रहा है, तो मुझे बताएं और मैं देखूंगा कि क्या मैं इसे संशोधित कर सकता हूं।


कोई कर रहे हैं exactपर Redirect reacttraining.com/react-router/web/api/Redirect कि तुलना में बहुत क्लीनर होगा <Route exact path="/" render={() => <Redirect to="/path" />} />कि मैं बजाय कर रहा हूं। कम से कम यह मुझे टाइपस्क्रिप्ट के साथ नहीं जाने देगा।
फिल्लूरन

2
क्या मैं सही ढंग से समझता हूं कि नेस्टेड / सब रूट (अब) जैसी कोई चीज नहीं है? क्या मुझे सभी मार्गों में आधार मार्ग की नकल करने की आवश्यकता है? क्या प्रतिक्रिया-राउटर 4 में रखरखाव योग्य तरीके से संरचित मार्गों के लिए कोई मदद नहीं मिलती है?
विल

5
@ मैं हैरान हूँ; क्या आपको कोई बेहतर उपाय मिला? मैं सभी स्थानों पर मार्ग नहीं बनाना चाहता, gosh
punkbit

1
यह काम करेगा लेकिन सुनिश्चित करें कि आपके पास बंडल / जेएस के लिए वेबपैक कॉन्फिगर करने के लिए सार्वजनिक पथ सेट है ", अन्यथा नेस्टेड रूट पेज रिफ्रेश पर काम नहीं करेंगे।
विक्रांत

6

कुछ इस तरह।

import React from 'react';
import {
  BrowserRouter as Router, Route, NavLink, Switch, Link
} from 'react-router-dom';

import '../assets/styles/App.css';

const Home = () =>
  <NormalNavLinks>
    <h1>HOME</h1>
  </NormalNavLinks>;
const About = () =>
  <NormalNavLinks>
    <h1>About</h1>
  </NormalNavLinks>;
const Help = () =>
  <NormalNavLinks>
    <h1>Help</h1>
  </NormalNavLinks>;

const AdminHome = () =>
  <AdminNavLinks>
    <h1>root</h1>
  </AdminNavLinks>;

const AdminAbout = () =>
  <AdminNavLinks>
    <h1>Admin about</h1>
  </AdminNavLinks>;

const AdminHelp = () =>
  <AdminNavLinks>
    <h1>Admin Help</h1>
  </AdminNavLinks>;


const AdminNavLinks = (props) => (
  <div>
    <h2>Admin Menu</h2>
    <NavLink exact to="/admin">Admin Home</NavLink>
    <NavLink to="/admin/help">Admin Help</NavLink>
    <NavLink to="/admin/about">Admin About</NavLink>
    <Link to="/">Home</Link>
    {props.children}
  </div>
);

const NormalNavLinks = (props) => (
  <div>
    <h2>Normal Menu</h2>
    <NavLink exact to="/">Home</NavLink>
    <NavLink to="/help">Help</NavLink>
    <NavLink to="/about">About</NavLink>
    <Link to="/admin">Admin</Link>
    {props.children}
  </div>
);

const App = () => (
  <Router>
    <div>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/help" component={Help}/>
        <Route path="/about" component={About}/>

        <Route exact path="/admin" component={AdminHome}/>
        <Route path="/admin/help" component={AdminHelp}/>
        <Route path="/admin/about" component={AdminAbout}/>
      </Switch>

    </div>
  </Router>
);


export default App;


6

मैं Switchरूट रूट की तुलना में नेस्टेड रूट को परिभाषित और परिभाषित करने में सफल रहा ।

<BrowserRouter>
  <Switch>
    <Route path="/staffs/:id/edit" component={StaffEdit} />
    <Route path="/staffs/:id" component={StaffShow} />
    <Route path="/staffs" component={StaffIndex} />
  </Switch>
</BrowserRouter>

संदर्भ: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md


आदेश को फिर से व्यवस्थित करना मेरे मुद्दे को तय करता है, हालांकि मुझे नहीं पता कि क्या इसका कोई दुष्प्रभाव होगा। लेकिन अभी के लिए काम कर रहे हैं .. धन्यवाद :)
Anbu369

2

आप Routes.js की तरह कुछ कोशिश कर सकते हैं

import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom';
import FrontPage from './FrontPage';
import Dashboard from './Dashboard';
import AboutPage from './AboutPage';
import Backend from './Backend';
import Homepage from './Homepage';
import UserPage from './UserPage';
class Routes extends Component {
    render() {
        return (
            <div>
                <Route exact path="/" component={FrontPage} />
                <Route exact path="/home" component={Homepage} />
                <Route exact path="/about" component={AboutPage} />
                <Route exact path="/admin" component={Backend} />
                <Route exact path="/admin/home" component={Dashboard} />
                <Route exact path="/users" component={UserPage} />    
            </div>
        )
    }
}

export default Routes

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Routes from './Routes';

class App extends Component {
  render() {
    return (
      <div className="App">
      <Router>
        <Routes/>
      </Router>
      </div>
    );
  }
}

export default App;

मुझे लगता है कि आप यहां से भी वही हासिल कर सकते हैं।


अच्छी बात! मैंने उसी तरह से सोचा जब जावा स्प्रिंग बूट ऐप डेवलपमेंट के बाद रिएक्ट के साथ शुरू हुआ। केवल एक चीज जो मैं बदलूंगा, वह है 'div' को 'Routes.js' में स्विच करना। और tbh, आप App.js में सभी मार्गों को परिभाषित कर सकते हैं, लेकिन इसे बाहर index.js फ़ाइल में लपेट सकते हैं उदाहरण के लिए (create-react-app)
पुनर्जन्म

हाँ आप सही है! मैंने इस तरह से लागू किया है इसलिए मैं इस विधि का उल्लेख कर रहा हूं।
अनिरुद्ध अग्रवाल

-6
interface IDefaultLayoutProps {
    children: React.ReactNode
}

const DefaultLayout: React.SFC<IDefaultLayoutProps> = ({children}) => {
    return (
        <div className="DefaultLayout">
            {children}
        </div>
    );
}


const LayoutRoute: React.SFC<IDefaultLayoutRouteProps & RouteProps> = ({component: Component, layout: Layout, ...rest}) => {
const handleRender = (matchProps: RouteComponentProps<{}, StaticContext>) => (
        <Layout>
            <Component {...matchProps} />
        </Layout>
    );

    return (
        <Route {...rest} render={handleRender}/>
    );
}

const ScreenRouter = () => (
    <BrowserRouter>
        <div>
            <Link to="/">Home</Link>
            <Link to="/counter">Counter</Link>
            <Switch>
                <LayoutRoute path="/" exact={true} layout={DefaultLayout} component={HomeScreen} />
                <LayoutRoute path="/counter" layout={DashboardLayout} component={CounterScreen} />
            </Switch>
        </div>
    </BrowserRouter>
);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.