Получение свойства из значения действия в Angular 9 & NgRx reducer - PullRequest
0 голосов
/ 29 мая 2020

У меня проблемы с получением свойства значения в редукторе NgRx. Я пытаюсь извлечь accessToken пользовательского объекта и сохранить его в состоянии. Однако, несмотря на то, что объект пользователя действителен и содержит действительный токен доступа, когда я пытаюсь получить токен доступа, он возвращает значение undefined.

В отладчике, если я наведу курсор на пользовательский объект, я могу увидеть полное значение со всеми свойствами, включая accessToken, но если я перейду к следующей строке и наведу курсор на объект accessToken, он покажет undefined.

import { createReducer, on } from '@ngrx/store';
import { User } from 'src/app/models/user.model';
import { AuthActions } from '../action-types';

export const authFeatureKey = 'auth';

export interface AuthState {
  user: User;
  accessToken: string;
}

export const initialAuthState: AuthState = {
  user: undefined,
  accessToken: undefined,
};

const reducer = createReducer(
  initialAuthState,

  on(AuthActions.signup, (state, action) => {
    return {
      user: action.user,
      accessToken: action.user.accessToken,
    };
  }),

  on(AuthActions.signin, (state, action) => {
    // split out to debug.
    const user = <User>action.user; // action.user returns a valid object
    const token = user.accessToken; // despite this being valid in the user object, returns undefined.
    return {
      user: action.user,
      accessToken: token,
    };
  }),

  on(AuthActions.signOut, () => {
    return {
      user: undefined,
      accessToken: undefined,
    };
  }),
);

export function authReducer(state, action) {
  return reducer(state, action);
}

Это действия:

import { createAction, props } from '@ngrx/store';
import { User } from '../../models/user.model';

export const signup = createAction('[SignUp Page] User SignUp', props<{ user: User }>());

export const signin = createAction('[SignIn Page] User SignIn', props<{ user: User }>());

export const signOut = createAction('[Top Menu] User SignOut');

и это селекторы:

import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromAuth from './reducers';

export const selectAuthState = createFeatureSelector<fromAuth.AuthState>(fromAuth.authFeatureKey);

export const isLoggedIn = createSelector(selectAuthState, (auth) => !!auth.user);

export const isLoggedOut = createSelector(isLoggedIn, (loggedIn) => !loggedIn);

export const getCurrentUser = createSelector(selectAuthState, (auth) => auth.user);

export const getAccessToken = createSelector(selectAuthState, (auth) => auth.accessToken);

Это auth.module.ts, показывающий импорт authReducer (как и просили)

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { AuthRoutingModule } from './auth-routing.module';
import { AuthService } from './services/auth.service';
import * as fromAuth from './store/reducers';
import { AuthEffects } from './store/auth-effects';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    AuthRoutingModule,
    HttpClientModule,
    StoreModule.forFeature(fromAuth.authFeatureKey, fromAuth.authReducer),
    EffectsModule.forFeature([AuthEffects]),
  ],
  providers: [AuthService],
})
export class AuthModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: AuthModule,
      providers: [AuthService],
    };
  }
}

Я заметил, что в этом состоянии он сохраняет значение несколько странно:

auth
    user
      user
         userName: "username1"
         email: "email@email.com"
         accessToken: "ey......7z"
         refreshToken: "xxx"

Таким образом, похоже, что он каким-то образом вкладывает пользовательский объект.

Ответы [ 2 ]

0 голосов
/ 01 июня 2020

Это была моя ошибка, служба передавала результат обратно как объект User:

  signin(credentials: SignInCredentials): Observable<User> {
    return this.http.post<User>('/api/signin', credentials);
  }

Однако на самом деле это был пользователь внутри объекта:

{
   user: {
      userName:
      ...
   }
}

Это вот где все пошло не так. Итак, я изменил службу, чтобы вернуть любой:

  signin(credentials: SignInCredentials): Observable<any> {
    return this.http.post<User>('/api/signin', credentials);
  }

, и изменил отправку действия:

this.authService
  .signin(this.credentials)
  .pipe(
    tap((data: any) => {
      this.store.dispatch(AuthActions.signin({ user: data.user }));
      this.router.navigateByUrl('/');
    }),

Чувствуя себя идиотом.

0 голосов
/ 29 мая 2020

action.user может быть действительным, это не означает, что он содержит всю необходимую информацию. Особенно, когда используется httpClient и его ответ приводится к любому типу.

Вам необходимо отладить эффект, который испускает AuthActions.signin, чтобы гарантировать, что созданный им пользователь содержит .accessToken значение.

...