2017-12-14 252 views
7

Muszę wprowadzić przepływ rejestracyjny za pomocą routera reagującego-4. Przepływ składa się z następujących etapów:Warunkowo zabezpieczające trasy (przepływ rejestracji użytkownika)

  1. Utwórz konto (email/pass)
  2. Potwierdź email
  3. Utwórz profil (dane takie jak City, Age etc, pola wymagane)

wymagania aplikacyjne:

  • Jeśli użytkownik nie jest zalogowany, zawsze powinien być przekierowany do Login strona
  • jeśli użytkownik jest zalogowany, ale e-mail nie został potwierdzony, powinien zawsze być przekierowany na stronę ConfirmEmail (niezależnie od tego, jaki URL wpisuje w pasku adresu URL, nawet po wczytaniu aplikacji po kilku dniach)
  • , jeśli użytkownik potwierdził wiadomość e-mail, ale nie jeszcze nie został utworzony profil, chcę, żeby zawsze być przekierowany do CreateProfile stronie

Więc jeśli użytkownik nie skończył jakiś krok chcę zawsze przekierować go do tego kroku (nawet po przeładunku aplikacji i niezależnie od tego, co URL wpisuje w przeglądarce).

Jako opcję chcę ograniczyć dostęp użytkownika do strony ConfirmEmail, jeśli już ją potwierdził (lub ograniczyć dostęp do strony CreateProfile, jeśli już utworzył profil).

Jak elegancko zaimplementować tę logikę za pomocą routera 4? Myślę, że jest to podstawowa/podstawowa cecha aplikacji, więc szukam dobrego, skalowalnego rozwiązania.

Również używam Redux, więc proszę zauważyć, że w pewnym momencie mam już następujące zmienne w stanie Redux: isLoggedIn, isEmailConfirmed, isProfileCreated.

Dzięki.

+0

Tomasz odpowiedź jest dobra, należy również użyć [Redux Persist] (https://github.com/rt2zz/redux-persist), aby utrzymać swój sklep redux w [LocalForage] (https://github.com/localForage/localForage) lub LocalStorage – Dyo

+0

Co rozumiesz przez wdrożenie rejestracji po zalogowaniu. Jak się zalogować do aplikacji bez rejestracji –

Odpowiedz

2

Nie określono, jak i kiedy zostanie ustawiony isLoggedIn, isEmailConfirmed, isProfileCreated, więc założyłem, że zostaną one ustawione w jakiś sposób w sklepie redux przed rozpoczęciem renderowania.

Myślę, że najlepszym narzędziem do tego zadania będzie użycie renderowania w trybie liniowym Route podobnym do auth workflow example in RR4 docs.

Zrobiłem sample CRA app, który robi to, czego potrzebujesz.

Jeśli index.js zmiany wartości właściwości w Redux /:

const INITIAL_STATE = { 
    isLoggedIn: false, 
    isEmailConfirmed: false, 
    isProfileCreated: false, 
} 

... aplikacja będzie używać go do renderowania odpowiedni widok, bez względu na to, co URL próbie dostępu. Na przykład, jeśli ustawisz isEmailConfirmed = true i isProfileCreated = false, wtedy jedyną dostępną trasą jest /create-profile (komponent CreateProfile). Jeśli użytkownik wykonał wszystkie kroki rejestracji i uzyskał isProfileCreated = true, będzie miał dostęp do każdej trasy, z wyjątkiem rejestracji.

Ulepszony Route nazwie AuthorizedRoute:

import React from 'react' 
import { Redirect, Route } from 'react-router-dom' 
import { connect } from 'react-redux' 

const AuthorizedRoute = ({ component: Component, isProfileCreated, isEmailConfirmed, isLoggedIn, ...rest }) => (
    <Route {...rest} render={props => { 
    //-- if user is fully registered - grant him every route except registration steps. 
    if (isProfileCreated) { 
     if (['/', '/create-account', '/create-profile', '/confirm-email'].includes(props.location.pathname)) { 
     return <Redirect to="/dashboard" /> 
     } else { 
     return <Component {...props} /> 
     } 
    } 

    //-- user is not fully registered so he needs to be redirected to next step... 
    if (isEmailConfirmed) { 
     if (props.location.pathname === '/create-profile') { 
     return <Component {...props} /> 
     } else { 
     return <Redirect to="/create-profile" /> 
     } 
    } 
    if (isLoggedIn) { 
     if (props.location.pathname === '/confirm-email') { 
     return <Component {...props} /> 
     } else { 
     return <Redirect to="/confirm-email" /> 
     } 
    } 

    //-- ... or allowed to use `Login` or `CreateAccount` page 
    if (props.location.pathname === '/' || props.location.pathname === '/create-account') { 
     return <Component {...props} /> 
    } 
    return <Redirect to="/" /> 
    }} /> 
) 

export default connect(
    (state) => ({ 
    isProfileCreated: state.isProfileCreated, 
    isEmailConfirmed: state.isEmailConfirmed, 
    isLoggedIn: state.isLoggedIn, 
    }), 
)(AuthorizedRoute) 

I tu są określone składniki, które są świadomi tej logiki:

class App extends Component { 
    render() { 
    return (
     <div> 
     <nav> 
      <Link to="/">login</Link> 
      <Link to="/create-account">create account</Link> 
      <Link to="/confirm-email">confirm email</Link> 
      <Link to="/create-profile">create profile</Link> 
      <Link to="/dashboard">dashboard</Link> 
     </nav> 
     <Switch> 
      <AuthorizedRoute exact path="/" component={Login} /> 
      <AuthorizedRoute path="/create-account" component={CreateAccount} /> 
      <AuthorizedRoute path="/confirm-email" component={ConfirmEmail} /> 
      <AuthorizedRoute path="/create-profile" component={CreateProfile} /> 
      <AuthorizedRoute path="/dashboard" component={Dashboard} /> 
      <Redirect to="/" /> 
     </Switch> 
     </div> 
    ) 
    } 
} 

Myślę, że najtrudniej jest rzeczywiście poprawnie zidentyfikować użytkownika i co jest dozwolone lub nie. Poza tym jest to tylko kwestia identyfikacji trasy, do której próbuje uzyskać dostęp i renderowania tej trasy lub przekierowania.

+0

Nie ma tutaj strony logowania. – zarcode

+0

@zarcode Masz rację. Zapomniałem o tym i wprowadziłem zmiany, aby to odzwierciedlić. – Tomasz