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

问题描述 投票:7回答:1

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

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

申请要求:

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

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

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

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

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

谢谢。

reactjs redux react-router react-router-v4
1个回答
2
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.