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