Wie leite ich mit dem React-Router auf eine andere Route um?

94

Ich versuche EINFACH mit dem React-Router ( Version ^ 1.0.3 ) zu tun , um zu einer anderen Ansicht umzuleiten, und ich werde nur müde.

import React from 'react';
import {Router, Route, Link, RouteHandler} from 'react-router';


class HomeSection extends React.Component {

  static contextTypes = {
    router: PropTypes.func.isRequired
  };

  constructor(props, context) {
    super(props, context);
  }

  handleClick = () => {
    console.log('HERE!', this.contextTypes);
    // this.context.location.transitionTo('login');
  };

  render() {
    return (
      <Grid>
        <Row className="text-center">          
          <Col md={12} xs={12}>
            <div className="input-group">
              <span className="input-group-btn">
                <button onClick={this.handleClick} type="button">
                </button>
              </span>
            </div>
          </Col>
        </Row>
      </Grid>
    );
  }
};

HomeSection.contextTypes = {
  location() {
    React.PropTypes.func.isRequired
  }
}

export default HomeSection;

Alles was ich brauche ist die Verwendung an '/ login' zu senden und das wars.

Was kann ich tun ?

Fehler in der Konsole:

Nicht erfasster Referenzfehler: PropTypes ist nicht definiert

Datei mit meinen Routen

// LIBRARY
/*eslint-disable no-unused-vars*/
import React from 'react';
/*eslint-enable no-unused-vars*/
import {Route, IndexRoute} from 'react-router';

// COMPONENT
import Application from './components/App/App';
import Contact from './components/ContactSection/Contact';
import HomeSection from './components/HomeSection/HomeSection';
import NotFoundSection from './components/NotFoundSection/NotFoundSection';
import TodoSection from './components/TodoSection/TodoSection';
import LoginForm from './components/LoginForm/LoginForm';
import SignupForm from './components/SignupForm/SignupForm';

export default (
    <Route component={Application} path='/'>
      <IndexRoute component={HomeSection} />
      <Route component={HomeSection} path='home' />
      <Route component={TodoSection} path='todo' />
      <Route component={Contact} path='contact' />
      <Route component={LoginForm} path='login' />
      <Route component={SignupForm} path='signup' />
      <Route component={NotFoundSection} path='*' />
    </Route>
);
Reagieren
quelle
Hallo! Können Sie Ihre routesDefinitionen veröffentlichen und auch, wenn es einen Grund gibt, warum Sie keine LinkKomponente verwenden? Erwähnen Sie auch, welche Fehler Sie erhalten.
Aarosil
Anstelle von Knopf <Link to="/login">Log In</Link>?
Aarosil
Welche Version des React-Routers verwenden Sie auch? Der Code für die prozedurale Umleitung hat sich in den Hauptversionen geändert.
mjhm
4
Für die Uncaught ReferenceErrorrufen Sie als an PropTypes, aber Sie importieren das nicht, Sie müssen PropTypes als sich selbst importieren oder verwendenReact.PropTypes
aarosil
1
@ JoshDavidMiller guter Punkt, aber ich werde nicht überrascht sein, react-routerAPI-Änderung innerhalb von 5 Minuten .. haha ​​Scherz, aber nur teilweise
aarosil

Antworten:

33

Für die einfache Antwort können Sie anstelle von die LinkKomponente von react-routerverwenden button. Es gibt Möglichkeiten, die Route in JS zu ändern, aber anscheinend brauchen Sie das hier nicht.

<span className="input-group-btn">
  <Link to="/login" />Click to login</Link>
</span>

Um dies programmgesteuert in 1.0.x zu tun, gefällt Ihnen dies in Ihrer clickHandler-Funktion:

this.history.pushState(null, 'login');

Entnommen aus dem Upgrade-Dokument hier

Sie sollten this.historyIhre Route-Handler-Komponente von platziert haben react-router. Wenn es sich um eine untergeordnete Komponente handelt, die unter der in der routesDefinition genannten liegt, müssen Sie diese möglicherweise weitergeben

Aarosil
quelle
2
Dies ist eine coole Lösung, aber der Grund, warum ich sie nicht verwende, ist, dass ich zuerst eine Art Validierung durchführen muss, also muss ich dies in eine Funktion if (true) { // redirect to login}einfügen , wie zum Beispiel: Deshalb habe ich das in einen onClick eingefügt Funktion
Reaktion
5
Sie können dies auch in JSX tun : {validation && <Link to="/login" />Click to login</Link>}. Wenn die Validierung falsch ist, wird nichts gerendert.
Aarosil
Ich weiß, was Sie meinen, aber ich brauche die Schaltfläche, um dort zu sein. Wenn die Validierung wahr ist, leiten Sie um, andernfalls sollte eine Fehlermeldung angezeigt werden.
Reagieren
@ TheUnnamed Ich habe die Antwort aktualisiert, um zu zeigen, wie es in JS geht
aarosil
1
> Uncaught Typeerror: kann nicht lesen Eigentum ‚pushstate‘ von undefined
Reaktion
90

1) React-Router> V5- useHistoryHook:

Wenn Sie über React >= 16.8funktionale Komponenten verfügen , können Sie den useHistory Hook des React-Routers verwenden .

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

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

    const handleClick = () => {
        history.push("/path/to/push");
    }

    return (
        <div>
            <button onClick={handleClick} type="button" />
        </div>
    );
}

export default YourComponent;

2) React-Router> V4 withRouterHOC:

Wie @ambar in den Kommentaren erwähnt hat, hat React-Router seine Codebasis seit V4 geändert. Hier sind die Dokumentationen - offiziell , mit Router

import React, { Component } from 'react';
import { withRouter } from "react-router-dom";

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

export default withRouter(YourComponent);

3) React-Router <V4 mit browserHistory

Sie können diese Funktionalität mit dem React-Router erreichen BrowserHistory. Code unten:

import React, { Component } from 'react';
import { browserHistory } from 'react-router';

export default class YourComponent extends Component {
    handleClick = () => {
        browserHistory.push('/login');
    };

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

4) Redux connected-react-router

Wenn Sie Ihre Komponente mit Redux verbunden und den Router für verbundene Reaktionen konfiguriert haben, müssen this.props.history.push("/new/url");Sie withRouterlediglich HOC nicht historyin die Komponenten-Requisiten injizieren .

// reducers.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';

export default (history) => combineReducers({
    router: connectRouter(history),
    ... // rest of your reducers
});


// configureStore.js
import { createBrowserHistory } from 'history';
import { applyMiddleware, compose, createStore } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers';
...
export const history = createBrowserHistory();

export default function configureStore(preloadedState) {
    const store = createStore(
        createRootReducer(history), // root reducer with router state
        preloadedState,
        compose(
            applyMiddleware(
                routerMiddleware(history), // for dispatching history actions
                // ... other middlewares ...
            ),
        ),
    );

    return store;
}


// set up other redux requirements like for eg. in index.js
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router';
import { ConnectedRouter } from 'connected-react-router';
import configureStore, { history } from './configureStore';
...
const store = configureStore(/* provide initial state if any */)

ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <> { /* your usual react-router v4/v5 routing */ }
                <Switch>
                    <Route exact path="/yourPath" component={YourComponent} />
                </Switch>
            </>
        </ConnectedRouter>
    </Provider>,
    document.getElementById('root')
);


// YourComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
...

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
          <div>
            <button onClick={this.handleClick} type="button">
          </div>
        );
      }
    };

}

export default connect(mapStateToProps = {}, mapDispatchToProps = {})(YourComponent);
Noushad
quelle
3
Scheint, als ob 'browserHistory' nicht mehr Teil des React-Routers ist.
Ambar
BrowserRouter hat keine Push-Funktion
Johnnyodonnell
@ambar @johnnyodonnell react-router-domtut
toinetoine
23

Wie leite ich mit dem React-Router auf eine andere Route um?

Wenn ein Benutzer beispielsweise auf einen Link klickt, <Link to="/" />Click to route</Link>sucht der React-Router /und Sie können Redirect toden Benutzer verwenden und an eine andere Stelle wie die Anmelderoute senden.

Aus den Dokumenten für ReactRouterTraining :

Wenn Sie a <Redirect>rendern, navigieren Sie zu einem neuen Ort. Der neue Speicherort überschreibt den aktuellen Speicherort im Verlaufsstapel, wie dies bei serverseitigen Umleitungen (HTTP 3xx) der Fall ist.

import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>

to: string, Die URL, zu der umgeleitet werden soll.

<Redirect to="/somewhere/else"/>

to: object, Ein Ort, an den umgeleitet werden soll.

<Redirect to={{
  pathname: '/login',
  search: '?utm=your+face',
  state: { referrer: currentLocation }
}}/>
jtlindsey
quelle
Die bereitgestellte Lösung gibt einen Fehler aus <Redirect> elements are for router configuration only and should not be rendered.
t1gor
9

Einfachste Lösung für das Web!

Aktuelle 2020
bestätigte die Zusammenarbeit mit:

"react-router-dom": "^5.1.2"
"react": "^16.10.2"

Benutze den useHistory()Haken!

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


export function HomeSection() {
  const history = useHistory();
  const goLogin = () => history.push('login');

  return (
    <Grid>
      <Row className="text-center">          
        <Col md={12} xs={12}>
          <div className="input-group">
            <span className="input-group-btn">
              <button onClick={goLogin} type="button" />
            </span>
          </div>
        </Col>
      </Row>
    </Grid>
  );
}
Scott Plunkett
quelle
Ausgezeichnet, war auf der Suche nach dem Haken Weg, es zu tun! Obwohl in meiner IDE die Warnung "Symbol kann nicht aufgelöst werden ..." angegeben ist, funktioniert sie!
Rafael Moni
7

Mit React-Router v2.8.1 (wahrscheinlich auch andere 2.xx-Versionen, aber ich habe es nicht getestet) können Sie diese Implementierung verwenden, um eine Router-Umleitung durchzuführen.

import { Router } from 'react-router';

export default class Foo extends Component {

  static get contextTypes() {
    return {
      router: React.PropTypes.object.isRequired,
    };
  }

  handleClick() {
    this.context.router.push('/some-path');
  }
}
Tom Van Rompaey
quelle
manchmal: this.context.router.history.push ('/ some-path');
嘉 道
4

Die einfachste Lösung ist:

import { Redirect } from 'react-router';

<Redirect to='/componentURL' />
Jackkobec
quelle
Aber ich erhalte einen Fehler: Invariante fehlgeschlagen: Sie sollten <Redirect> nicht außerhalb eines <Router> verwenden
Prateek Gupta
Hast du versucht zu wickeln?
Jackkobec