web-dev-qa-db-fra.com

ngrx-store-localstorage angulaire ne stocke pas de données après le rechargement

J'essaie d'intégrer ngrx à mon processus d'authentification en utilisant ngrx-store-localstorage pour stocker le jeton au cours des sessions du navigateur.

Lorsque je me connecte, je peux voir la valeur du jeton dans la mémoire, comme

{"token":{"token":"e5cb6515-149c-44df-88d1-4ff16ff4169b","expiresIn":10385,"expiresAt":1512082478397},"authenticated":true,"error":false}

mais quand, par exemple, je modifie une page et le rechargement de l'application, j'ai 

{"token":null,"authenticated":false,"error":false}

Les actions du code

import { Action } from '@ngrx/store';

import { AuthenticationTokenInterface } from '../authentication.interface';

export const LOGIN = 'LOGIN';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGIN_FAILED = 'LOGIN_FAILED';
export const LOGOUT = 'LOGOUT';
export const SET_TOKEN = 'SET_TOKEN';

export class Login implements Action {
  readonly type = LOGIN;
  constructor(public payload: {username: 'string',password: 'string'}) {}
}

export class LoginSuccess implements Action {
  readonly type = LOGIN_SUCCESS;
}

export class LoginFailed implements Action {
  readonly type = LOGIN_FAILED;
}

export class Logout implements Action {
  readonly type = LOGOUT;
}

export class SetToken implements Action {
  readonly type = SET_TOKEN;

  constructor(public payload: AuthenticationTokenInterface) {}
}

export type AuthenticationActions =  Login | LoginSuccess | LoginFailed | Logout | SetToken;

effets

@Injectable()
export class AuthenticationEffects {
  @Effect()
  login$ = this.actions$.ofType(AuthenticationActions.LOGIN)
  .pipe(
    mergeMap((action: AuthenticationActions.Login) => {
       return this.authenticationService.login(action.payload)
       .pipe(
        mergeMap((token:AuthenticationTokenInterface) => {
          this.router.navigate(['/main/dashboard']);
          return [
            { type: AuthenticationActions.LOGIN_SUCCESS },
            { type: AuthenticationActions.SET_TOKEN, payload: token }
          ]
        }),
        catchError(() => {
          return  of({ type: AuthenticationActions.LOGIN_FAILED })
        })
       )
     })
  );
  @Effect({dispatch: false})
  logout$ = this.actions$.ofType(AuthenticationActions.LOGOUT)
  .pipe(
    switchMap(()=>{
      this.router.navigate(['/logout']);
      return this.authenticationService.logout();
    })
  );

  constructor(
    private actions$: Actions,
    private router: Router,
    private authenticationService: AuthenticationService
  ) {}
}

réducteurs

export interface State {
  token: AuthenticationTokenInterface;
  authenticated: boolean;
  error: boolean;
}

const initialState: State = {
  token: null,
  authenticated: false,
  error: false
};

export function authenticationReducer(
  state = initialState,
  action: AuthenticationActions.AuthenticationActions
):State {
  switch (action.type) {
    case (AuthenticationActions.LOGIN_SUCCESS):
      return {
        ...state,
        authenticated: true,
      };
    case (AuthenticationActions.LOGIN_FAILED):
      return {
        ...state,
        error: true
      };
    case (AuthenticationActions.LOGOUT):
      return {
        ...state,
        token: null,
        authenticated: false
      };
    case (AuthenticationActions.SET_TOKEN):
      return {
        ...state,
        token: action.payload
      };
    default:
      return state;
  }
}

réducteurs (App)

export interface AppState {
  authentication: fromAuthentication.State
}

export const reducers: ActionReducerMap<AppState> = {
  authentication: fromAuthentication.authenticationReducer
};

Module d'application

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

imports: [
  StoreModule.forRoot(
      reducers,
      {metaReducers}
  ),
  EffectsModule.forRoot([AuthenticationEffects]),
]
8
Whisher

Vous devez ajouter la clé rehydrate à l'appel de la fonction localStorageSync.

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

Voir: https://github.com/btroncone/ngrx-store-localstorage/blob/master/README.md pour plus de détails.

11
Mateusz Witkowski

Ce dont vous avez besoin est simplement d’ajouter une option de rehydrate boolean définie comme true dans votre fichier app.module.

Cela extraira ou récupérera les données de localStorage dans l'état initial de votre réducteur pendant le rechargement.

Votre localStorageSync doit être configuré en tant que ...

localStorageSync(
 {keys: ['authentication'],
  rehydrate: true     <------ add this line
}) (reducer);
2
Foram Sangani