I need to implement registration flow using react-router-4. Flow consist of following steps:
Application requirements:
Login
pageConfirmEmail
page (regardless of what URL he type in url address bar, even after loading app after few days)CreateProfile
pageSo if user didn't finished some step I want always redirect him to this step (even after reloading application and regardless of what URL he type in browser).
As an option I want to restrict user from accessing ConfirmEmail
page if he already confirmed it (or restrict access to CreateProfile
page if he already created profile).
How to elegantly implement this logic using React router 4? I think it's a core/fundamental feature of application, so I'm looking for good, scalable solution.
Also i'm using Redux, so please note that at some point I already have following variables in Redux state: isLoggedIn
, isEmailConfirmed
, isProfileCreated
.
Thanks.
You didn't specify how or when isLoggedIn
, isEmailConfirmed
, isProfileCreated
will be set so I assumed they will be already somehow set in the redux store before rendering starts.
I think that best tool for this task will be to use inline Route
rendering similar to auth workflow example in RR4 docs.
I have made sample CRA app that does what you require.
If you change values of properties in redux/index.js:
const INITIAL_STATE = {
isLoggedIn: false,
isEmailConfirmed: false,
isProfileCreated: false,
}
... the app will use it to render appropriate view, no matter what URL you try to access. For example, if you set isEmailConfirmed=true and isProfileCreated=false then the only route you will have access is /create-profile
(CreateProfile component).
If the user however completed every step of registration steps and isProfileCreated=true he will then have access to every route except those of registration.
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 defined components that are aware of 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 the hardest part is to actually correctly identify the user and what he is allowed or not to do. Other than that it's just a matter of identifying route he is trying to access and rendering that route or redirecting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With