Conditionally pinning routes (user registration flow)

I need to inject a registration flow using response-router-4. The flow consists of the following steps:

  • Create an account (email / pass)
  • Confirm Email
  • Create a profile (profile data, such as City, Age, etc., required fields)

Application Requirements:

  • If the user is not logged in, he should always be redirected to the Login page.
  • if the user is logged in but has not confirmed the email address, he should always be redirected to the ConfirmEmail page (no matter what URL he enters in the address bar of the URL, even after downloading the application a few days later).
  • if the user has confirmed the email address but has not yet created a profile, I want him to always be redirected to the CreateProfile page

So, if the user has not finished any step, I want to always redirect him to this step (even after restarting the application and no matter what URL he enters in the browser).

As an option, I want to restrict the user’s access to the ConfirmEmail page if he has already confirmed it (or to restrict access to the CreateProfile page if he has already created a profile).

How to elegantly implement this logic with React router 4? I believe this is the main / main function of the application, so I am looking for a good, scalable solution.

I also use Redux, so isLoggedIn in isEmailConfirmed that at some point I already have the following variables in Redux state: isLoggedIn , isEmailConfirmed , isProfileCreated .

Thanks.

+7
reactjs redux react-router react-router-v4
source share
1 answer

You did not specify how and when isLoggedIn , isEmailConfirmed , isProfileCreated will be installed, so I assumed that they would be somehow set in the reduction storage before rendering.

I think that the best tool for this task would be to use the built-in Route rendering, a similar workflow example in RR4 documents .

I made an example CRA application that does what you need.

If you change the property values ​​in redux / index.js :

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

... the application will use it to display the appropriate view, no matter what URL you are trying to get. For example, if you set isEmailConfirmed = true and isProfileCreated = false , then the only path you will have access to is /create-profile (CreateProfile component). If the user has completed each step of the registration steps and isProfileCreated = true , he will have access to each route, except for those that are registered.

Enhanced Route named 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) 

And here are certain components that know this logic:

 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> ) } } 

I think that the most difficult part is to correctly identify the user and what he is allowed or not to do. In addition, it is only a matter of identifying the route to which he is trying to access, and providing this route or redirecting.

+2
source share

All Articles