从 Angular 9 和 NgRx reducer 中的操作值中检索 属性
Retrieving a property from an action value in Angular 9 & NgRx reducer
我在检索 NgRx reducer 中某个值的 属性 时遇到问题。我正在尝试提取用户对象的 accessToken 并将其存储在状态中。但是,尽管用户对象有效并且包含有效的 accessToken,但当我尝试检索 accessToken 时,它 returns 未定义。
在调试器中,如果我将鼠标悬停在用户对象上,我可以看到包括 accessToken 在内的所有属性的完整值,但如果我跳到下一行并将鼠标悬停在 accessToken 对象上,它会显示未定义。
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"
所以它看起来像是在以某种方式嵌套用户对象。
action.user
可以是有效的,并不代表它包含所有需要的信息。特别是当使用 httpClient 并且它的响应被转换为任何类型时。
您需要调试发出 AuthActions.signin
的效果以确保它生成的用户包含 .accessToken
值。
这是我的错误,服务将结果作为用户对象传回:
signin(credentials: SignInCredentials): Observable<User> {
return this.http.post<User>('/api/signin', credentials);
}
然而,它实际上是对象内部的用户:
{
user: {
userName:
...
}
}
这就是问题所在。所以我将服务更改为 return 和 any:
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('/');
}),
感觉自己像个白痴。
我在检索 NgRx reducer 中某个值的 属性 时遇到问题。我正在尝试提取用户对象的 accessToken 并将其存储在状态中。但是,尽管用户对象有效并且包含有效的 accessToken,但当我尝试检索 accessToken 时,它 returns 未定义。
在调试器中,如果我将鼠标悬停在用户对象上,我可以看到包括 accessToken 在内的所有属性的完整值,但如果我跳到下一行并将鼠标悬停在 accessToken 对象上,它会显示未定义。
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"
所以它看起来像是在以某种方式嵌套用户对象。
action.user
可以是有效的,并不代表它包含所有需要的信息。特别是当使用 httpClient 并且它的响应被转换为任何类型时。
您需要调试发出 AuthActions.signin
的效果以确保它生成的用户包含 .accessToken
值。
这是我的错误,服务将结果作为用户对象传回:
signin(credentials: SignInCredentials): Observable<User> {
return this.http.post<User>('/api/signin', credentials);
}
然而,它实际上是对象内部的用户:
{
user: {
userName:
...
}
}
这就是问题所在。所以我将服务更改为 return 和 any:
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('/');
}),
感觉自己像个白痴。