我需要使用react-router-4实现注册流程。流程包括以下步骤:
申请要求:
Login
页面ConfirmEmail
页面(无论他在URL地址栏中输入什么URL,即使在几天后加载应用程序之后)CreateProfile
页面因此,如果用户没有完成某个步骤,我希望始终将他重定向到此步骤(即使在重新加载应用程序之后,无论他在浏览器中输入什么URL)。
作为一个选项,我想限制用户访问ConfirmEmail
页面,如果他已经确认它(或限制访问CreateProfile
页面,如果他已经创建了配置文件)。
如何使用React路由器4优雅地实现这个逻辑?我认为这是应用程序的核心/基本功能,因此我正在寻找良好,可扩展的解决方案。
我也在使用Redux,所以请注意,在某些时候我已经在Redux状态下有以下变量:isLoggedIn
,isEmailConfirmed
,isProfileCreated
。
谢谢。
你没有指定如何或何时设置isLoggedIn
,isEmailConfirmed
,isProfileCreated
所以我假设它们在渲染开始之前已经以某种方式设置在redux存储中。
我认为这个任务的最佳工具是使用类似于Route
的内联auth workflow example in RR4 docs渲染。
我做了sample CRA app,做你需要的。
如果更改redux / index.js中的属性值:
const INITIAL_STATE = {
isLoggedIn: false,
isEmailConfirmed: false,
isProfileCreated: false,
}
...无论您尝试访问哪个URL,应用程序都会使用它来呈现适当的视图。例如,如果设置isEmailConfirmed = true且isProfileCreated = false,那么您将有权访问的唯一路径是/create-profile
(CreateProfile组件)。然而,如果用户完成了注册步骤的每个步骤并且isProfileCreated = true,那么他将可以访问除注册之外的每个路径。
增强的Route
名为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)
这里是定义的组件,它们知道这个逻辑:
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>
)
}
}
我认为最难的部分是实际正确识别用户以及他允许或不允许做什么。除此之外,它只是识别他试图访问和渲染该路线或重定向的路线。