368 votes

Routes imbriquées avec le routeur de réaction v4

Je suis actuellement aux prises avec l'imbrication des itinéraires à l'aide de réagir routeur v4.

L'exemple le plus proche est la voie de config dans le Réagir-Routeur v4 Documentation.

Je veux partager mon app en 2 parties.

Un frontend et une zone d'administration.

Je pensais à quelque chose comme ceci:

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

L'interface a une autre mise en page et le style de la zone d'administration. Dans le frontpage de l'itinéraire accueil, a propos et donc on devrait être l'enfant routes.

/la maison doit être rendue dans le composant Frontpage et /admin/maison doit être rendue dans le composant d'arrière-plan.

J'ai essayé quelques variations, mais j'ai toujours terminé à ne pas frapper /home ou /admin/home.

Edit - 19.04.2017

Parce que ce post a beaucoup de points de vue maintenant j'ai mis à jour avec la solution finale. J'espère que cela aide quelqu'un.

Edit - 08.05.2017

Retiré vieux solutions

Solution finale:

C'est la solution finale, je suis à l'aide de la droite maintenant. Cet exemple a également une erreur globale de la composante traditionnel, à la page 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;

401voto

Lyubomir Points 10274

Dans réagissent-routeur-v4 vous n'avez pas de nid <Routes />. Au lieu de cela, vous les placez à l'intérieur un autre <Component />.


Par exemple

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

devrait devenir

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

avec

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

Voici un exemple de base directement à partir de la réaction-routeur de la documentation.

210voto

davnicwil Points 1417

Il est vrai que, pour nest les Routes, vous devez les placer dans le composant enfant de la Route.

Toutefois, si vous préférez, plus 'inline' la syntaxe plutôt que de casser votre parcours à travers des composants, vous pouvez utiliser le render prop sur l' <Route> vous souhaitez nid sous, avec une ligne apatrides composante fonctionnelle, comme suit:

<BrowserRouter>

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

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

</BrowserRouter>

Si vous êtes intéressé, pourquoi render doit être utilisé à la place de component, c'est pour arrêter la ligne de la composante d'être remonté sur chaque rendu. Voir la documentation pour plus de détails.

Notez également que l'exemple ci-dessus utilise Réagir 16 Fragments d'envelopper le imbriqués les Routes, juste pour le rendre un peu plus propre. Avant de Réagir, de 16 vous pouvez simplement utiliser un conteneur <div> au lieu de cela ici.

54voto

jar0m1r Points 570

Je voulais juste dire à réagir-routeur v4 radicalement changé depuis que cette question a été postée/answed.

Il n'y a pas d' <Match> composant plus! <Switch>est de s'assurer que seul le premier match est rendu. <Redirect> bien .. redirige vers une autre voie. L'utilisation ou la quitter exact , soit en - ou exclure une correspondance partielle.

Voir les docs. Ils sont grands. https://reacttraining.com/react-router/

Voici un exemple, je l'espère, n'est pas utilisable pour répondre à votre question.

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

Espérons qu'il a aidé, laissez-moi savoir. Si cet exemple n'est pas de répondre à votre question, dites-moi et je vais voir si je peux le modifier.

9voto

Sanjeev Shakya Points 57

Quelque chose comme ça.

 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; 

3voto

Aniruddh Agarwal Points 567

Vous pouvez essayer quelque chose comme 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;
 

Je pense que vous pouvez réaliser la même chose d'ici aussi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X