NGRX Select:选择如何与内部对象一起使用?
NGRX Select: How is the selection working with an inner object?
我是 NGRX 的新手并尝试获得 运行 一个简单的 NGRX 示例。我有一个名为 LoginState 的接口,它是我商店中的对象。 LoginState 包含一个 IUser 类型的用户对象。如果我 select 在我的组件中的这个对象上,如果用户对象发生变化,我不会返回 IUser(我的效果似乎工作正常,因为如果我只是在商店上订阅,我会返回所有状态更改)。
这是我的配置:
app.module.ts
imports: [
...
StoreModule.forRoot({loginState: loginReducer})
]
login.actions.ts
export const userLoginRequest = createAction('[Login] user login request');
export const userLoginFacebookSuccess = createAction('[Login] user login facebook success', props<{socialUser: SocialUser}>());
export const userLoginSuccess = createAction('[Login] user login success', props<{user: IUser}>());
login.reducer.ts
export interface LoginState {
request: boolean;
socialUser?: SocialUser;
user?: IUser;
}
export const initialState: LoginState = {
request: false
};
const reducer = createReducer(initialState,
on(userLoginRequest, (status, action) => ({
...status,
request: true
})),
on(userLoginFacebookSuccess, (status, action) => ({
...status,
socialUser: action.socialUser
})),
on(userLoginSuccess, (status, action) => ({
...status,
user: action.user
}))
);
export function loginReducer(sta: LoginState, action: Action): LoginState {
return reducer(sta, action);
}
login.effects.ts
import { userLoginRequest, userLoginSuccess, userLoginFacebookSuccess } from './login.action';
@Injectable()
export class LoginEffects {
loginFacebook$ = createEffect(() => this.actions$.pipe(
ofType(userLoginRequest),
switchMap(() =>
this.authService.loginFacebook()
.pipe(
map((socialUser) => {
this.tokenService.saveToken(socialUser.authToken);
return userLoginFacebookSuccess({socialUser});
})
)
)
)
);
loadUser$ = createEffect(() => this.actions$.pipe(
ofType(userLoginFacebookSuccess),
switchMap((act) =>
this.userService.getUser(act.socialUser)
.pipe(
map((usr) => userLoginSuccess({user: usr}))
)
)
)
);
constructor(
private actions$: Actions,
private authService: AuthWrapperService,
private tokenService: TokenStorageService,
private userService: UserService
) {}
}
Login.component.ts
export class LoginComponent implements OnInit {
localUser: IUser;
constructor(
private router: Router,
private store: Store<LoginState>
){}
signInWithFB(): void {
this.store.dispatch(userLoginRequest());
}
ngOnInit() {
this.store.select(selectUser).subscribe( (user) => {
console.log(JSON.stringify(user, undefined, 2));
}
);
}
}
const loginState = (state: LoginState) => state;
export const selectUser = createSelector(
loginState,
(state: LoginState) => state.user
);
非常感谢您的帮助!
干杯,
你
您拥有的代码很好,您需要记住 ngrx
会立即选择数据,即使您没有。
因此,当 this.store.select(selectUser)
在使用加载之前第一次执行时,它将 return 未定义,这是预期的。
处理完 userLoginSuccess
后,我们在商店中有一个用户,选择器将发出所需用户的第二个值。
如果您希望始终获得用户,则可以过滤流中的发射。另请注意,您所在的州在 loginState
以下,因此您需要使用 createFeatureSelector
.
const loginStateFeature = createFeatureSelector<LoginState>('loginState');
export const selectUser = createSelector(
loginStateFeature,
(state: LoginState) => state.user
);
ngOnInit() {
this.store.select(selectUser).pipe(
filter(user => !!user), // skipping falsy emits.
).subscribe((user) => {
console.log(JSON.stringify(user, undefined, 2));
});
}
我是 NGRX 的新手并尝试获得 运行 一个简单的 NGRX 示例。我有一个名为 LoginState 的接口,它是我商店中的对象。 LoginState 包含一个 IUser 类型的用户对象。如果我 select 在我的组件中的这个对象上,如果用户对象发生变化,我不会返回 IUser(我的效果似乎工作正常,因为如果我只是在商店上订阅,我会返回所有状态更改)。
这是我的配置:
app.module.ts
imports: [
...
StoreModule.forRoot({loginState: loginReducer})
]
login.actions.ts
export const userLoginRequest = createAction('[Login] user login request');
export const userLoginFacebookSuccess = createAction('[Login] user login facebook success', props<{socialUser: SocialUser}>());
export const userLoginSuccess = createAction('[Login] user login success', props<{user: IUser}>());
login.reducer.ts
export interface LoginState {
request: boolean;
socialUser?: SocialUser;
user?: IUser;
}
export const initialState: LoginState = {
request: false
};
const reducer = createReducer(initialState,
on(userLoginRequest, (status, action) => ({
...status,
request: true
})),
on(userLoginFacebookSuccess, (status, action) => ({
...status,
socialUser: action.socialUser
})),
on(userLoginSuccess, (status, action) => ({
...status,
user: action.user
}))
);
export function loginReducer(sta: LoginState, action: Action): LoginState {
return reducer(sta, action);
}
login.effects.ts
import { userLoginRequest, userLoginSuccess, userLoginFacebookSuccess } from './login.action';
@Injectable()
export class LoginEffects {
loginFacebook$ = createEffect(() => this.actions$.pipe(
ofType(userLoginRequest),
switchMap(() =>
this.authService.loginFacebook()
.pipe(
map((socialUser) => {
this.tokenService.saveToken(socialUser.authToken);
return userLoginFacebookSuccess({socialUser});
})
)
)
)
);
loadUser$ = createEffect(() => this.actions$.pipe(
ofType(userLoginFacebookSuccess),
switchMap((act) =>
this.userService.getUser(act.socialUser)
.pipe(
map((usr) => userLoginSuccess({user: usr}))
)
)
)
);
constructor(
private actions$: Actions,
private authService: AuthWrapperService,
private tokenService: TokenStorageService,
private userService: UserService
) {}
}
Login.component.ts
export class LoginComponent implements OnInit {
localUser: IUser;
constructor(
private router: Router,
private store: Store<LoginState>
){}
signInWithFB(): void {
this.store.dispatch(userLoginRequest());
}
ngOnInit() {
this.store.select(selectUser).subscribe( (user) => {
console.log(JSON.stringify(user, undefined, 2));
}
);
}
}
const loginState = (state: LoginState) => state;
export const selectUser = createSelector(
loginState,
(state: LoginState) => state.user
);
非常感谢您的帮助!
干杯,
你
您拥有的代码很好,您需要记住 ngrx
会立即选择数据,即使您没有。
因此,当 this.store.select(selectUser)
在使用加载之前第一次执行时,它将 return 未定义,这是预期的。
处理完 userLoginSuccess
后,我们在商店中有一个用户,选择器将发出所需用户的第二个值。
如果您希望始终获得用户,则可以过滤流中的发射。另请注意,您所在的州在 loginState
以下,因此您需要使用 createFeatureSelector
.
const loginStateFeature = createFeatureSelector<LoginState>('loginState');
export const selectUser = createSelector(
loginStateFeature,
(state: LoginState) => state.user
);
ngOnInit() {
this.store.select(selectUser).pipe(
filter(user => !!user), // skipping falsy emits.
).subscribe((user) => {
console.log(JSON.stringify(user, undefined, 2));
});
}