有条件保护路线(用户注册流程)

时间:2017-12-14 15:39:46

标签: reactjs redux react-router react-router-v4

我需要使用react-router-4实现注册流程。流程包括以下步骤:

  1. 创建帐户(电子邮件/通行证)
  2. 确认电子邮件
  3. 创建个人资料(个人资料详情,如城市,年龄等,必填字段)
  4. 申请要求:

    • 如果用户未登录,则应始终将其重定向到Login页面
    • 如果用户已登录,但未确认电子邮件,则应始终将其重定向到ConfirmEmail页面(无论他在网址地址栏中输入的是哪个网址,即使在几天后加载应用后也是如此)
    • 如果用户确认了电子邮件,但尚未创建个人资料,我希望他始终被重定向到CreateProfile页面

    因此,如果用户没有完成某个步骤,我希望始终将他重定向到此步骤(即使在重新加载应用程序后,无论他在浏览器中输入什么URL)。

    作为一个选项,我想限制用户访问ConfirmEmail页面,如果他已经确认了(或限制访问CreateProfile页面,如果他已经创建了个人资料)。

    如何优雅使用React路由器4实现此逻辑?我认为这是应用程序的核心/基本功能,因此我正在寻找良好,可扩展的解决方案。

    我也在使用Redux,所以请注意,在某些时候我已经在Redux状态下有以下变量:isLoggedInisEmailConfirmedisProfileCreated

    感谢。

1 个答案:

答案 0 :(得分:2)

您没有指定如何或何时设置isLoggedInisEmailConfirmedisProfileCreated,因此我假设在渲染开始之前,它们已经以某种方式设置在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>
    )
  }
}

我认为最难的部分是实际正确识别用户以及他允许或不允许做什么。除此之外,只是确定他试图访问和渲染该路线或重定向的路线。

相关问题