2015-11-19 13 views
21

Voglio configurare React Router nel modo seguente. Se una determinata rotta è abbinata, l'utente viene reindirizzato a un'altra. Documentation afferma che è possibile, ma non fornisce il modo esatto per raggiungerlo. Qualcuno ha idea di questo?Come utilizzare la funzione di reindirizzamento di React Router?

type EnterHook = (nextState: RouterState, replaceState: RedirectFunction, callback?: Function) => any; 

type RedirectFunction = (state: ?LocationState, pathname: Pathname | Path, query: ?Query) => void; 

risposta

36

EDITVedi altra risposta per i nuovi, non deprecata sintassi reagire-router


C'è un buon esempio di come utilizzare il gancio onEnter nel auth-flow example. Ecco il codice rilevante:

function requireAuth(nextState, replaceState) { 
    if (!auth.loggedIn()) 
    replaceState({ nextPathname: nextState.location.pathname }, '/login') 
} 

render((
    <Router history={history}> 
    <Route path="/" component={App}> 
     <Route path="login" component={Login} /> 
     <Route path="logout" component={Logout} /> 
     <Route path="about" component={About} /> 
     <Route path="dashboard" component={Dashboard} onEnter={requireAuth} /> 
    </Route> 
    </Router> 
), document.getElementById('example')) 

Come si può vedere, quando il percorso /dashboard si accede alla funzione requireAuth è chiamato. Riceve due argomenti: nextState, che è un oggetto RouterState che rappresenta lo stato che l'utente sta per immettere e replaceState, uno RedirectFunction che può essere chiamato per sostituire quello stato con qualcos'altro. In questo caso, se l'utente non è connesso, requireAuth chiamate replaceState simili:

replaceState({ nextPathname: nextState.location.pathname }, '/login') 

Il secondo argomento è ovviamente il percorso l'utente viene reindirizzato. Il primo argomento è un oggetto che può contenere qualsiasi dato che vogliamo che il gestore di route (in questo caso il componente Login) abbia. Qui il nome percorso che l'utente stava cercando di andare a (/dashboard) è impostato come proprietà nextPathname, quindi dopo aver effettuato l'accesso l'utente può essere reindirizzato a quella pagina (vedere il metodo handleSubmit nel componente Login).

Se l'utente è connesso, requireAuth non fa nulla, e dal momento che non è mai chiamato replaceState il percorso funziona come al solito, vale a dire la componente Dashboard è reso.

+0

Grazie per questa risposta esauriente! – Jason

+0

Uso il rendering universale e sfortunatamente questo metodo comporta 302 reindirizzamenti. C'è un modo in cui sarei in grado di utilizzare reindirizzamenti 301 in caso di richiesta di un server? –

16

Capita a chiunque legga questa domanda a partire dal react-router 2.0.0, replaceState (stato, percorso, query) è ora deprecato. Ora devi usare replace (location) con un descrittore di posizione.

https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#link-to-onenter-and-isactive-use-location-descriptors

Dal loro guida:

// v1.0.x 
(nextState, replaceState) => replaceState(null, '/foo') 
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' }) 

// v2.0.0 
(nextState, replace) => replace('/foo') 
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } }) 
+0

Ciao.Quando usiamo la funzione replace, non mantiene lo stato del negozio al reindirizzamento. Come lo posso fare? Voglio dire, come passare lo stato del negozio (insieme ai dispatcher di azioni) nella prossima route – myDoggyWritesCode

+1

Ciao @ user3241111 Ho aggiunto una risposta qui sotto che spero possa aiutarti a chiarire. – justswim

10

Ecco un esempio di come fare questo con react-router 2.0.0 (usando replace invece di replaceState):

In router. jsx:

function requireAuth(nextState, replace) { 
    if (!userExists()) { 
    replace({ 
     pathname: '/signin', 
     state: { nextPathname: nextState.location.pathname } 
    }) 
    } 
} 

export const renderRoutes =() => (
    <Router history={browserHistory}> 
     <Route path="protectedRoute" component={Protected} onEnter={requireAuth} /> 
     <Route path="signin" component={SignIn} /> 
    </Route> 
    </Router> 
); 

Poi, all'interno SignIn componente, è possibile reindirizzare un segno di successo in questo modo:

import { browserHistory } from 'react-router'; 

signInFunction({params}, (err, res) => { 
    // Now in the sign in callback 
    if (err) 
    alert("Please try again") 
    else { 
    const location = this.props.location 
    if (location.state && location.state.nextPathname) { 
     browserHistory.push(location.state.nextPathname) 
    } else { 
     browserHistory.push('/') 
    } 
    } 
}) 
+0

Grazie per la risposta. Ci sono 2 cose diverse dal tuo esempio sopra e dal mio scenario. La prima è che la mia autenticazione è basata su TOKEN e NON mi piace reindirizzarlo a un modulo di accesso che è una route (non nel mio caso) nella stessa applicazione. 2 ° caso .. Nel momento in cui stai facendo sostituire (percorso: '/ signin' ....) so già se il mio utente è loggato, condizione "if (userExists())" è SEMPRE VERO poiché è sicuramente loggato. Voglio solo sostituire la pagina '/ notFound' ma lo stato dell'applicazione si sta perdendo nel caricare questa rotta. Voglio proteggere alcuni componenti dagli utenti registrati. – myDoggyWritesCode

+0

La mia app è isomorfa, quindi il problema è in arrivo. Ho inviato il mio TOKEN per l'autenticazione ad altri URL insieme a "return url" che ha autenticato il TOKEN e invia i reindirizzamenti a "return url". quindi se faccio "cb()", reindirizza all'URL protetto e conserva anche i miei UserDetails ma se ho usato "replace ('/ notFound')" allora dimentica lo stato .. Nell'istanza in cui devo cb() o sostituire (..), lo stato del server ha già userDetails che voglio passare alla route 'notFound'. – myDoggyWritesCode

+0

Grazie @justswim Ha risolto il mio ciclo infinito – mike00

Problemi correlati