Anguar 7 использовал NGRX и сохранял токен в localStorage - PullRequest
0 голосов
/ 29 ноября 2018

В моем Angular-приложении я использовал NGRX store и у меня возникли проблемы с сохранением пользовательского токена.Иногда я перезагружаю свою страницу и теряю все.

В app.component.ts реализуем OnInit и добавляем туда:

this.store.select('auth').subscribe(event => {
  if (event.token) {
    window.localStorage.setItem('token', JSON.stringify(event.token));
  }
});

if (window.localStorage.getItem('token')) {
  const token = JSON.parse(window.localStorage.getItem('token'));
  this.store.dispatch(new AuthActions.SetToken(token));
}

И создаем эффект:

@Effect()
this.actions$.pipe(
    ofType<AuthActions.TrySignin> (
        AuthActions.AuthActionTypes.TRY_SIGNIN
    ),
        switchMap(action => {
            return this.httpClient.put('http://localhost:8080/api/signin', {
                username: action.payload.username,
                password: action.payload.password
            }, {
                    observe: 'body',
                    responseType: 'text'
                }).pipe(
                    map(
                        token => {
                            this.router.navigate(['/']);
                            return new AuthActions.SetToken(token);
                        }
                    ),
                    catchError(error => {
                        return of(new AuthActions.AuthFailed(error));
                    }
                    )
                );

        }
        )
);

Itправильно?

Ответы [ 4 ]

0 голосов
/ 21 марта 2019

По умолчанию состояние вашего приложения сбрасывается при обновлении страницы.

Что вам нужно сделать, это сохранить ваше состояние «auth» в постоянное хранилище, например, localstorage / sessionstorage.

И восстановить состояние из localalstorage / sessionstorage при запуске.

Я создал библиотеку, чтобы легко справиться с этим: https://github.com/larscom/ngrx-store-storagesync

  1. Выполнить:

npm install --save @ larscom / ngrx-store-storagesync

Настройка метаредуктора

Конфигурация будет выглядеть примерно так: 1021 *

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule, ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
import { storageSync } from '@larscom/ngrx-store-storagesync';
import * as fromAuth from './auth/reducer';

export const reducers: ActionReducerMap<ISomeState> = { 
  auth: fromAuth.reducer
};

export function storageSyncReducer(reducer: ActionReducer<any>): ActionReducer<any> {
  return storageSync<ISomeState>({
    features: [
      // saves the auth state to sessionStorage
      { stateKey: 'auth' }
    ],     
    storage: window.sessionStorage
  })(reducer);
}

const metaReducers: Array<MetaReducer<any, any>> = [storageSyncReducer];

@NgModule({
  imports: [BrowserModule, StoreModule.forRoot(reducers, { metaReducers })]
})
export class AppModule {}

Вот и все, если вы перезагрузите страницу, состояние будет восстановлено изsessionStorage (в данном случае)

0 голосов
/ 30 ноября 2018

Я бы посоветовал вам не делать этого внутри ваших компонентов.Их будет сложнее тестировать, плюс вы можете получить один и тот же код в разных компонентах.

Вместо использования вы можете сделать это внутри эффектов, как предложил Maciej, для другого примера см. https://github.com/tomastrajan/angular-ngrx-material-starter/blob/master/src/app/examples/form/form.effects.ts#L20

Но лично мне нравится использовать для этого мета-редуктор - см. https://github.com/timdeschryver/ngrx-family-grocery-list/blob/master/src/app/groceries/reducers/groceries.reducer.ts#L165

Например:

export function persistStateReducer(_reducer: ActionReducer<State>) {
  const localStorageKey = '__auth';
  return (state: State | undefined, action: Action) => {
    if (state === undefined) {
      const persisted = localStorage.getItem(localStorageKey);
      return persisted ? JSON.parse(persisted) : _reducer(state, action);
    }

    const nextState = _reducer(state, action);
    localStorage.setItem(localStorageKey, JSON.stringify(nextState));
    return nextState;
  };
}
0 голосов
/ 03 декабря 2018
@Injectable()
export class FormEffects {
  constructor(
    private actions$: Actions<Action>,
    private localStorageService: LocalStorageService
  ) {}

  @Effect({ dispatch: false })
  persistForm = this.actions$.pipe(
    ofType<ActionFormUpdate>(FormActionTypes.UPDATE),
    tap(action =>
      this.localStorageService.setItem(FORM_KEY, { form: action.payload.form })
    )
  );
}
0 голосов
/ 29 ноября 2018

почему бы не сохранить токен в локальном хранилище напрямую?

У этого подхода есть недостаток, который вы должны помнить, чтобы подписаться на сохранение и сохранение токена всякий раз, когда он появляется.Во-вторых, это плохо, когда auth состояние выдает данные, на которые подписывается ваша подписка, сохранит токен, даже если раньше он был корректным.

Получение кода токена пахнет хорошо.

...