【问题标题】:I lose information about user when refreshing page? Angular 2+ NgRx store刷新页面时我丢失了有关用户的信息? Angular 2+ NgRx 商店
【发布时间】:2020-03-19 07:49:53
【问题描述】:

我需要发布用户信息,但我正在丢失它以刷新。如何设置 isAuthenticated 变量,我们不会在刷新时失去价值? 也许您不需要查看大部分代码,只需告诉我现在如何修复它 你需要的一段我的代码:

组件:

  getState: Observable<any>;
  isAuthenticated: false;
  user = null;
  errorMessage = null;
  globalisAuthenticated = null;
  constructor(public dialog: MatDialog, private store: Store<AppState>) {
    this.getState = this.store.select(selectAuthState);
   }
  ngOnInit() {
    this.getState.subscribe((state) => {
      this.isAuthenticated = state.isAuthenticated;
      this.user = state.user;
      this.errorMessage = state.errorMessage;
      // console.log("is" , this.isAuthenticated)
      localStorage.setItem("isAuthenticated", state.isAuthenticated);
    });

减速机:

export interface State {
  // is a user authenticated?
  isAuthenticated: boolean;
  // if authenticated, there should be a user object
  user: User | null;
  // error message
  errorMessage: string | null;
}

export const initialState: State = {
  isAuthenticated: false,
  user: null,
  errorMessage: null
};

    export function reducer(state = initialState, action: All): State {
      switch (action.type) {
        case AuthActionTypes.LOGIN_SUCCESS: {
          return {
            ...state,
            isAuthenticated: true,
            user: {
              token: action.payload.token,
              email: action.payload.email
            },
            errorMessage: null
          };
        }
        case AuthActionTypes.LOGIN_FAILURE: {
          return {
            ...state,
            errorMessage: 'Incorrect email and/or password.'
          };
        }
        default: {
          return state;
        }
      }
    }

效果:

  @Effect()
LogIn: Observable<any> = this.actions
  .ofType(AuthActionTypes.LOGIN)
  .map((action: LogIn) => action.payload)
  .switchMap(payload => {
    return this.authService.logIn(payload.email, payload.password)
      .map((user) => {
        console.log(user);
        return new LogInSuccess({token: user.token, email: payload.email});
      })
      .catch((error) => {
        console.log(error);
        return Observable.of(new LogInFailure({ error: error }));
      });
  });

  @Effect({ dispatch: false })
LogInSuccess: Observable<any> = this.actions.pipe(
  ofType(AuthActionTypes.LOGIN_SUCCESS),
  tap((user) => {
    console.log("User",  user);
    localStorage.setItem('token', user.payload.token);
    this.snackBar.open("Uspesno ste ste prijavili.", null, {
      duration: 5000,
      verticalPosition: 'bottom',
      horizontalPosition: 'right'
   });
  })
);

状态:

export interface AppState {
  authState: auth.State;
}

export const reducers = {
  auth: auth.reducer
};

export const selectAuthState = createFeatureSelector<AppState>('auth');

您能告诉我一种避免在刷新时丢失数据的方法吗? 如果您需要更多信息,请问我。 目前这一切正常。但是当我刷新时,我会丢失所有内容,但令牌在本地存储中。

更新更新更新 我添加了这个,但又没有工作

  import { StoreModule, ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
  import { localStorageSync } from 'ngrx-store-localstorage';
  import { reducers } from './reducers';


  // const reducers: ActionReducerMap<IState> = {todos, visibilityFilter};

  export function localStorageSyncReducer(reducer: ActionReducer<any>): ActionReducer<any> {
    return localStorageSync({keys: ['todos']})(reducer);
  }
  const metaReducers: Array<MetaReducer<any, any>> = [localStorageSyncReducer];

【问题讨论】:

  • 您必须将metaReducers 添加到您的StoreModule,如下所示:StoreModule.forRoot(reducers, { metaReducers, ... }

标签: angular store ngrx


【解决方案1】:

这是您应该对 NgRx 的期望。每次刷新浏览器时,您都需要重新获取用户。有多种方法可以做到这一点。我使用的是 JWT 身份验证,所以状态更新过程如下所示:

  1. 用户通过输入用户名和密码登录
  2. Angular 成功验证用户身份并将颁发的 JWT 保存到 localStorage
  3. 用户刷新页面,导致状态丢失。这不是问题,因为在组件的 ngOnInit() 挂钩中,您的代码应该检查 JWT 令牌。如果在本地存储中找不到 JWT,它会立即将身份验证状态设置为“注销”。如果它确实找到了 JWT 令牌,它会分派一个新操作,我们将其称为 GET_USER
  4. GET_USER 操作将产生单一效果。此效果将向您的 /api/user 路由发送 API GET 请求。

此时,您可能想知道两件事。首先,您可能想知道 GET 请求的目的是什么?好吧,GET 请求不会立即生效。显然,您将需要某种 HTTP 标头与 GET 请求一起发送,以便后端可以确定您要获取的用户。为此,您可以设置HttpInterceptor。此拦截器将拦截每个传出的 HTTP 请求并附加存储在 localStorage 中的 JWT 令牌。

其次,您可能想知道后端将如何使用 JWT 令牌在数据库中查找用户。后端/api/user 路由会做以下事情:

  1. 从 HTTP Authorization 标头(由 Angular HttpInterceptor 填充)获取 JWT 令牌
  2. 使用jsonwebtoken等库验证JWT
  3. 如果 JWT 有效,jsonwebtoken 库将对其进行解码。颁发令牌时,您应该已将用户 ID 保存在 JWT 有效负载的 sub 属性中。您现在可以使用 sub 属性从数据库中检索用户。
  4. 返回检索到的用户

好的,我们可以回到原来的流程。请记住,所有这些都是由GET_USER 操作引起的,该操作产生了对/api/user 的GET 请求

  1. 此时,您应该可以访问效果中的用户对象。您现在将返回另一个操作,例如 GET_USER_SUCCESS,并将用户对象作为参数传递给该操作。
  2. GET_USER_SUCCESS 将有一个 reducer 来设置应用程序的身份验证状态。例如,您可以将属性 isAuthenticated 设置为 true,并将属性 user 设置为附加到 GET_USER_SUCCESS 操作负载的用户对象。

总之,NgRx 在每次刷新时清除状态是设计使然。在页面加载时填充用户当然不是一个简单的过程,但一旦实施,您将拥有可预测的用户身份验证流程。

【讨论】:

  • 如果每次我都需要从服务器重新获取数据,存储或状态管理是什么意思????
【解决方案2】:

试试这个

  export function localStorageSyncReducer(reducer: ActionReducer<any>): ActionReducer<any> {
     return localStorageSync( {keys: ['auth'], rehydrate: true})(reducer);
  }

【讨论】:

  • 你能告诉我什么是键吗?什么是认证?从位置这个数据来吗?谢谢
【解决方案3】:

您可以将此值保存到浏览器的 localStorage 为:

localStorage.setItem("auth", JSON.stringify(this.isAuthentificated));

然后,当您访问应用程序时,获取值。

this.isAuthentificated = JSON.parse(localStorage.getItem("auth"));

但是,当你注销时,你需要在localStorage上设置值为false,或者删除key。 (我更喜欢第一个)

1) localStorage.removeItem("auth");

2)localStorage.setItem("auth", false);

【讨论】:

  • 我可以存储我的布尔变量 isAuthentificated 吗?
  • 是的,你可以存储它,但你需要在登录/注销时更新或创建/删除它
【解决方案4】:

刷新时丢失状态是正常的。您将需要自己保存状态或使用诸如 https://www.npmjs.com/package/ngrx-store-localstorage 之类的库。

【讨论】:

  • 你有关于如何实现这个包的教程吗?我是角度新手
  • @AleksandarMihailovic:我不知道,但是包中的说明很简单,并且包含示例代码。
  • 你用过包吗?我复制/粘贴代码示例,但同样无效。看看更新答案。
  • 您是否将其添加到当前模块并像示例中那样注册了 metaReducers?从您的描述中不清楚您添加代码的位置。
  • 看我的图片ibb.co/7K93yLh 但在此之前我也有一个reduce from my state import { reducers } from './store/app.states';这是 module.app 文件@cisse
猜你喜欢
  • 2021-05-29
  • 2017-10-21
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 2018-06-04
  • 1970-01-01
  • 2021-12-08
  • 2020-11-20
相关资源
最近更新 更多