【问题标题】:Why componentDidMount() is the better place to evaluate user authentication?为什么 componentDidMount() 是评估用户身份验证的更好地方?
【发布时间】:2019-12-18 11:16:48
【问题描述】:

我正在关注一个身份验证教程,我正在尝试理解这一点:

componentDidMount() {
    this.props.firebase.auth.onAuthStateChanged(authUser => {
      authUser
        ? this.setState({ authUser })
        : this.setState({ authUser: null });
    });
  }

如果在组件渲染之后调用componentDidMount(),为什么要在渲染之后调用评估用户是否登录的函数?

我认为这样做的结果是:

  1. React 呈现未经身份验证的页面
  2. 之后,它会评估用户是否已通过身份验证
  3. 最终渲染出认证页面

代替:

  1. 评估用户是否通过身份验证
  2. 呈现经过身份验证的页面

你能说我在周期的哪个部分错了吗?

我知道componentDidMount()是用来不阻塞页面渲染的流程,但是如果用户之前有一个会话,然后再次进入该网站,他将无法访问私有页面,直到呈现公共页面并调用onAuthStateChanged()

【问题讨论】:

  • 您在“评估用户是否已通过身份验证”这一步是错误的。它实际上分为两个步骤(发送请求/接收响应):1. 发送请求以评估(这里你呈现加载器) 2. 接收 ok 响应(这里你呈现经过身份验证的页面) 3. 接收错误响应(这里你重定向到登录页面)
  • 如果您考虑将 componentWillMount 用于该用例 read react docs about why you shouldn't do it
  • @AngelLuis 我不确定我是否理解你。你怎么能在你的页面之前加载smth?有很多方法可以进行身份​​验证。请描述您希望您的身份验证过程如何。
  • @Arseniy-II 所以你认为更好的方法是,例如:应用程序状态(authUser: null, firstLoad: true),在评估用户是否登录时放置一个加载动画,更新状态,根据状态进行重定向,最后将状态firstLoad更新为false,以避免在状态会话的其余部分出现Loading动画。

标签: reactjs


【解决方案1】:

考虑到完全不鼓励使用像 componentWillMount() 这样的方法,处理这种情况的最佳方法之一是:

  1. 创建一个状态来评估 React 组件是否第一次渲染:this.state = { firstTime: true }
  2. 如果this.state.firsTime 为真,则渲染加载动画组件
  3. 之后会调用componentDidMount(),这里会调用判断是否登录的函数
  4. 如果用户登录或未登录,将使用结果更新this.state.authUser,并将this.state.firstLoad 更改为false
  5. 在下一次渲染中,由于this.state.firstTime 为假,不会渲染加载组件。这次会检查this.state.authUser的结果并渲染对应的组件

【讨论】:

    【解决方案2】:

    React 文档说要在 componentDidMount 中进行 api 调用,因为您可以在此处设置状态并在渲染中查看它们。

    您无需跟踪firstTime

    componentDidMount(){
      if(!this.state.auth){
        ..makecall.then(authUser =>{
            this.setState({authUser})
            localStorage.setState("authUser",authUser)
         })
      }
    }
    render(
     if(!this.state.authUser){
      return <div>Loading</div>
     }
     return(
       return <div>
       ...
       ... 
       </div>
     )
    )
    

    您也可以使用私有路由。获取 authUser 令牌后,将其存储在 localstorage 中并

        const PrivateRoute = ({ component: Component, ...rest }) => (
          if(localstorage.getItem("authUser")) {
            return <Route {...rest} render={(props) => (
                 <Component authUser={localstorage.getItem("authUser")} {...props} />
              }
               return <Redirect to={{
                  pathname: '/login',
                  state: { from: props.location }
                }} />
          )}
        )
      ..
      .. 
       export default function App(){
         return (
            <Router>
             <Route path="/login" component={Login}/>
             <PrivateRoute path='/protected' component={Protected} />
            </Router>
    }
    

    您需要在用户访问任何路线时始终对其进行验证,因此这是一种简单的方法。它将在一个地方检查身份验证,如果未通过身份验证,则重定向到登录页面。
    如果为了更高的安全性/良好的代码目的,您也需要对令牌进行验证。您可以在 PrivateRoute 函数或 componentDidMount 中执行此操作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多