Router v4

Client-seitiges Routing

Ziel-Anwendung

Warum Routing?

Mappen von URLs auf Komponenten
(Navigation findet ohne Server-Roundtrip statt)

Komponenten halten (Teil) des Zustandes der Anwendung
Welche Komponente ist sichtbar (Master oder Detail)?
Welche Daten werden dafür geladen (z.B. Greeting Id)

Herausforderungen

Auf Änderungen der URL reagieren
Ableiten des Zustandes aus der URL
Wenn sich die URL ändert, kein Server roundtrip

Hierarchische Komponentenstrukturen

Beim Klick auf Links etc aktualisieren der URL

React Router

Router

Top-Level-Objekt, das einmalig (oben) in der Komponenten Hierarchie eingebunden werden muss

Mehrere Ausprägungen zum Arbeiten mit den URL und der Browser History:

  • HashRouter: codiert Pfad in angehängten Hash (#/greetings)
  • BrowserRouter: codiert Pfad direkt in URL (/greetings)


import {HashRouter as Router} from "react-router-dom";

const app = <Router><GreetingController/></Router>;

ReactDOM.render(app, document.getElementById(...));
            

Route

  • Kann überall in der Anwendung verwendet werden, wo Pfad-abhängig Komponenten ausgewählt werden sollen
  • Mit path wird der Pfad übergeben, für den die Route matchen soll
  • Mit component wird die Komponente übergeben

import {HashRouter as Router, Route} from "react-router-dom";

const app = <Router>
    <Route path="/greet/:greetingId" component={GreetingDisplayController}/>
    <Route path="/" component={GreetingController}/>
</Router>;

ReactDOM.render(app, document.getElementById(...));
            

Route

  • Statt einer Komponente kann eine Funktion übergeben werden, die eine Komponente zurückliefert
  • Ermöglicht es, zusätzliche Properties an die Komponente zu übergeben
  • Kann unterschiedliche Komponenten zurückliefern (z.B. für Authorisierung)
  • 
    <Route path="/"
      render={() => {
        return loggedIn ? <GreetingMaster greetings={initialGreetings} />
                        :
                        <LoginForm />
                        }
    />
                

Pfade

  • Sind per Default gültig für Teilstrings
  • Mit exact kann das Verhalten verändert werden
    
    // trifft zu für / und /greeting
    <Route path="/" component={GreetingController}/>
    // trifft nur zu für /
    <Route path="/" exact component={GreetingController}/>
                
  • Route ohne path matcht immer
  • Kann variable Segmente enthalten:
    
    <Route path="/greeting/:greetingId"
              component={<GreetingDisplay />} />
    
    // in GreetingDisplay kann die greetingId über
    // this.props.match.params.greetingId abgefragt werden
                

Switch

  • Wenn mehrere path-Ausdrücke matchen, werden mehrere Komponenten gerendert (z.B. "/" und "/greetings")
  • Switch sorgt dafür, dass nur die erste Komponente im Block gerendert wird

import {HashRouter as Router, Route, Switch} from "react-router-dom";

const app = <Router>
  <Switch>
    <Route path="/greet/:greetingId" component={GreetingDisplayController}/>
    <Route path="/" component={GreetingController}/>

    // "No match": ohne Pfad
    <Route component={NotFoundPage}/>

  </Switch>
</Router>;

ReactDOM.render(app, document.getElementById(...));
            

Router Properties für Komponente

Der Router übergibt drei Properties an die gerenderte Komponente (oder an die render()-Funktion)

  • match: Enthält u.a. die Parameter aus dem Pfad (match.params.xyz)
  • history: Zum Arbeiten mit der History (z.B. push() zum Navigieren)
  • location: Der aktuelle Pfad (z.B. pathname, search)

const HelloComponent = ({match, history, location}) => (
  <div>
    <h1>Hello, {match.params.name}</h1>
    <small>The current path is: {location.pathname}</small>
    <button onClick={() => history.push('/greetings')}>Show Greetings</button>
  </div>
);

// ...
<Route path="/greet/:name" component={HelloComponent}/>

            

Links

Mit Link und NavLink können Links erzeugt werden

  • Mit to wird das Ziel angegeben
  • Gerendert wird per default ein a Element
  • URL wird entsprechend der History (Browser oder Hash) erzeugt
  • Mit activeClassName und activeStyle auf NavLink können Styles übergeben werden, die angewendet werden, wenn der Link der aktiven Route entspricht

import {Link, NavLink} from "react-router-dom";
<Link to='/greetings'>Show all greetings</Link>
<NavLink to='/greeting/me' activeClassName="highlight">Greet me</NavLink>