wake-up-neo.net

Programmgesteuert mit Reakt-Router navigieren

Ich entwickle eine Anwendung, in der ich prüfe, ob der Benutzer nicht loggedIn ist. Ich muss das Anmeldeformular anzeigen, andernfalls dispatch eine action, die die Route ändern und andere Komponenten laden würde. Hier ist mein Code:

    render() {
         if (isLoggedIn) {
             // dispatch an action to change the route
         }
         // return login component
         <Login />
    }

Wie kann ich das erreichen, da ich den Zustand innerhalb der Renderfunktion nicht ändern kann.

32
Gaurav Mehta

Bedenken Sie, dass Sie react-router v4 verwenden

Verwenden Sie Ihre Komponente mit withRouter und verwenden Sie history.Push von Requisiten, um die Route zu ändern. Sie müssen withRouter nur verwenden, wenn Ihre Komponente keine Router-Requisiten empfängt. Dies kann in Fällen der Fall sein, in denen Ihre Komponente ein verschachteltes untergeordnetes Element einer vom Router gerenderten Komponente ist und Sie die Router-Requisiten nicht an sie übergeben haben oder wann Die Komponente ist überhaupt nicht mit dem Router verbunden und wird als separate Komponente von den Routen dargestellt.

import {withRouter} from 'react-router';

class App extends React.Component {
     ...
     componenDidMount() {
        // get isLoggedIn from localStorage or API call
        if (isLoggedIn) {
             // dispatch an action to change the route
             this.props.history.Push('/home');
        }
     }
     render() {
         // return login component
         return <Login />
    }
}


export default withRouter(App);

Wichtige Notiz

Wenn Sie withRouter verwenden, um zu verhindern, dass Updates von .__ blockiert werden. shouldComponentUpdate, es ist wichtig, dass withRouter die .__ umschließt. Komponente, die shouldComponentUpdate implementiert. Zum Beispiel, wenn mit Redux:

// Das geht um shouldComponentUpdate

withRouter(connect(...)(MyComponent))

// Das tut nicht 

connect(...)(withRouter(MyComponent))

oder Sie könnten Redirect verwenden

import {withRouter} from 'react-router';

class App extends React.Component {
     ...
     render() {
         if(isLoggedIn) {
              return <Redirect to="/home"/>
         }
         // return login component
         return <Login />
    }
}

Mit react-router v2 or react-router v3 können Sie context verwenden, um die Route dynamisch zu ändern

class App extends React.Component {
     ...
     render() {
         if (isLoggedIn) {
             // dispatch an action to change the route
             this.context.router.Push('/home');
         }
         // return login component
         return <Login />
    }
}

App.contextTypes = {
    router: React.PropTypes.object.isRequired
}
export default App;

oder verwenden 

import { browserHistory } from 'react-router';
browserHistory.Push('/some/path');
29
Shubham Khatri

In der reakt-router version 4:

import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'

const Example = () => (

  if (isLoggedIn) {
    <OtherComponent />

  } else {

    <Router>
      <Redirect Push to="/login" />
      <Route path="/login" component={Login}/>
    </Router>

  }
)

const Login = () => (
    <h1>Form Components</h1>
    ...
)

export default Example;
3
tgrrr

Dies ist mein Handle loggedIn. react-router v4

PrivateRoute darf path eingeben, wenn der Benutzer angemeldet ist, und das Token unter localStorge speichern.

    function PrivateRoute({ component: Component, ...rest }) {
     return (
        <Route
          {...rest}
          render={props => (localStorage.token) ? <Component {...props} /> : (
            <Redirect
              to={{
                pathname: '/signin',
                state: { from: props.location },
              }}
            />
          )
          }
        />
      );
    }

Definieren Sie hier alle Pfade in Ihrer App

export default (
  <main>
    <Switch>
      <Route exact path="/signin" component={SignIn} />
      <Route exact path="/signup" component={SignUp} />
      <PrivateRoute path="/" component={Home} />
    </Switch>
  </main>
);
1
Quốc Vũ Vy

Eine andere Alternative besteht darin, dies mit asynchronen Aktionen im Thunk-Stil zu behandeln (die sicher sind/Nebeneffekte haben dürfen).

Wenn Sie Thunk verwenden, können Sie dasselbe history-Objekt sowohl in Ihre <Router>-Komponente als auch in die Thunk-Aktionen einfügen, indem Sie thunk.withExtraArgument wie folgt verwenden:

import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
import { createBrowserHistory } from "history"
import { applyMiddleware, createStore } from "redux"
import thunk from "redux-thunk"

const history = createBrowserHistory()

const middlewares = applyMiddleware(thunk.withExtraArgument({history}))
const store = createStore(appReducer, middlewares)

render(
  <Provider store={store}
    <Router history={history}>
      <Route path="*" component={CatchAll} />
    </Router
  </Provider>,
appDiv)

In Ihren Aktionserstellern haben Sie eine history-Instanz, die sicher mit ReactRouter verwendet werden kann. Sie können also einfach ein reguläres Redux-Ereignis auslösen, wenn Sie nicht angemeldet sind:

// meanwhile... in action-creators.js
export const notLoggedIn = () => {
  return (dispatch, getState, {history}) => {
    history.Push(`/login`)
  }
}

Ein weiterer Vorteil ist, dass die URL jetzt einfacher zu handhaben ist, sodass wir Weiterleitungsinformationen in die Abfragezeichenfolge usw. einfügen können.

Sie können auch weiterhin versuchen, diese Überprüfung in Ihren Render-Methoden durchzuführen. Wenn dies jedoch Probleme verursacht, sollten Sie dies in componentDidMount oder an anderer Stelle im Lebenszyklus tun (obwohl ich auch den Wunsch verstehe, bei Stateless Functional Compeonents zu bleiben!)

Sie können weiterhin Redux und mapDispatchToProps verwenden, um den Aktionsersteller in Ihr Unternehmen einzuspeisen, sodass Ihre Komponente nur noch lose mit Redux verbunden ist.

1
Chris Jaynes

Ich konnte history in zustandslosen Funktionskomponenten mit withRouter wie folgt verwenden (erforderlich, um die TypeScript-Warnung zu ignorieren):

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

...

type Props = { myProp: boolean };

// @ts-ignore
export const MyComponent: FC<Props> = withRouter(({ myProp, history }) => {

...

})
0
bruddha
render(){ 

    return (
        <div>  
            { this.props.redirect ? <Redirect to="/" /> :'' } 
            <div>
                add here component codes
            </div>
        </div>
    );
} 
0
Araz Babayev

Diejenigen, die Probleme bei der Implementierung auf reag-router v4 haben. Hier ist eine funktionierende Lösung für die programmgesteuerte Navigation durch die Apprea.

history.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()

App.js OR Route.jsx. Übergeben Sie die Geschichte als Requisite an Ihren Router.

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>

Sie können Push() zum Navigieren verwenden.

import history from './history' 

...

render() {
     if (isLoggedIn) {
         history.Push('/test') // this should change the url and re-render Test component
     }
     // return login component
     <Login />
}

Vielen Dank für diesen Kommentar: https://github.com/ReactTraining/react-router/issues/3498#issuecomment-301057248

0
reflexgravity

Ich würde vorschlagen, dass Sie Connected-React-Routerhttps://github.com/supasate/connected-react-router es ist gut dokumentiert und einfach zu konfigurieren

0
Denis Rudov