【问题标题】:How to maintain the authenticated user state on page refresh with react如何使用反应在页面刷新时维护经过身份验证的用户状态
【发布时间】:2019-11-15 15:13:37
【问题描述】:

我有一些受保护的路由器,但我需要在页面刷新时保持状态。

import React from 'react'
import { Route, Redirect, Switch } from 'react-router-dom'

const auth = {
    isAuthenticated: true // this would be an http call to get user data
}

const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={(props) => (
        auth.isAuthenticated === true
        ? <Component {...props} />
        : <Redirect to="/login" />
    )} />
)

const Main = () => {

    return (
        <Switch>
            <Route path="/login" exact strict component={Login}/>
            <Route path="/logout" exact strict component={Logout}/>
            <PrivateRoute path="/profile" exact strict component={Profile}/>
        </Switch>
    )
}

export default Main

我应该在哪里拨打服务电话?在主应用程序中?在上下文中?

更新:我在 Main 中添加了一个检查,它调用发送我存储的令牌的 api。该调用可能返回 200 和数据或 401

const auth = {
    isAuthenticated: Api.status() // this is just a fetch to /status endpoint 
        .then(
            status => {
                console.log(status);
                return true;
            },
            error => {
                console.log(error);
                return false;
            }
        )
}

但是当我点击 /profile 时,它​​会立即将我重定向到登录(因为 isAuthenticated 是假的)

我的问题完全基于用户刷新页面(F5)其他场景工作正常的场景。对不起,如果我不够清楚,很高兴再次澄清任何事情!

【问题讨论】:

  • 您可能希望使用localStorageIndexedDB 在状态更改时存储状态,并在重新加载页面时从中恢复。
  • 这可能会产生另一个问题。就像检查过期的令牌一样。我还需要进行服务调用以获取应该在应用程序的所有页面中持续存在的用户详细信息(姓名、电子邮件等)。
  • 嗨@Jurrian 实际上这就是我之前提到的关于存储过期 jwt 的问题,可以通过调用传递该令牌来解决这个问题,如果调用失败则删除令牌。但这几乎是我的问题。我应该在哪里进行这个需要在每次页面刷新时执行的 http 调用
  • 这对标题有点误导。如果您要在组件加载时通过 http 调用检索状态,那么您不需要存储它。因此,您的问题似乎更像是在询问是否 a.) 每次都进行调用是一种好习惯,或者 b) 有条件的替代方案和存储状态的方法。但是您的代码并未反映最初的尝试。你试过什么?

标签: reactjs


【解决方案1】:

在我看来,最好的方法是 local storage 将令牌保存在那里 在您的应用程序的根组件中的 componentDidMount() 中调度一个操作,并将令牌存储在 readucer state

【讨论】:

    【解决方案2】:

    您可以实现如下所示的身份验证上下文:https://usehooks.com/useAuth/

    此外,将用户存储在 localStorage(或您偏好的存储)中,当 auth-context 挂载时,从 localStorage 读取并设置初始值,如下所示:

    const [user, setUser] = useState(JSON.parse(localStorage.getItem('user')));

    这样,在重新加载页面时,受保护的路由将自动重定向(或它们应该在经过身份验证的状态下执行的任何操作)。

    【讨论】:

      【解决方案3】:

      在这种情况下,我会制作一个 AuthContext 组件。通过使用上下文提供程序,您可以在应用中的任何位置访问用户登录状态。

      import { createContext } from 'react';
      
      const AuthContext = createContext({
        token: null,
        userId: null,
        login: () => {},
        logout: () => {}
      });
      
      export default AuthContext;
      

      并在您的应用程序的最高级别提供此信息。

      import React, { useState } from 'react';
      import { Route, Switch } from 'react-router-dom';
      import AuthContext from './context/AuthContext';
      
      function App() {
        const [token, setToken] = useState(null);
        const [userId, setUserId] = useState(null);
      
        const login = (token, userId) => {
          setToken(token);
          setUserId(userId);
        };
      
        const logout = () => {
          setToken(null);
          setUserId(null);
        };
      
        return (
           <Switch>
              <Route path="/login" exact strict component={Login}/>
              <Route path="/logout" exact strict component={Logout}/>
              <PrivateRoute path="/profile" exact strict component={Profile}/>
           </Switch>
        )
      }
      
      export default App;
      

      然后在登录/注销表单中调用数据库或本地存储。

      import React, { useContext } from 'react';
      import AuthContext from '../context/AuthContext';
      
      function Auth() {
        const { login } = useContext(AuthContext);
      
        const submitHandler = () => {
          // Make the call here
        };
      
        return (
          <Form onSubmit={submitHandler}>
           // Put your login form here
          </Form>
        );
      }
      
      export default Auth;
      

      【讨论】:

      • 重新加载 /profile 页面时会发生什么?从我看到的上下文只会为令牌和用户 ID 返回 null。因为生成您存储的令牌的调用仅在 /login 上进行
      • 您应该将令牌保存在某处。您可以在本地或在服务器上执行此操作。这样当向服务器发出请求时,您可以验证令牌。
      • 我认为您应该观看有关此的教程。我是 Maximilian Schwarzmuller & WesBos 的忠实粉丝,所以看看他们。如果您有具体问题,请在此处提问。
      • 看来你可以使用一些理论
      • 嗯.. 是的,使用上下文是一个很好的建议,但并不真正适用。这个答案的适用部分可以改进.. React Hooks 可能不需要解释(但可能值得参考),但将状态恢复到 AuthContext 的概念并不完全清楚(它是自动的吗? ?)。此外,您可以包含一个检查AuthContext 中的属性的示例(已加载状态)。
      猜你喜欢
      • 2013-01-27
      • 2021-05-22
      • 1970-01-01
      • 2021-06-05
      • 2014-12-11
      • 2021-03-10
      • 2018-08-20
      • 1970-01-01
      • 2019-07-30
      相关资源
      最近更新 更多