如何解决查询商店时出现 Angular NGRX 错误:类型错误:无法读取未定义的属性“地图”
我已在我的 angular 应用程序中实现了 NGRX 效果,但出现以下错误。我不确定我是否在组件中正确使用选择器来查询商店?
core.js:6162 ERROR TypeError: Cannot read property 'map' of undefined
at ngrx-entity.js:21
at ngrx-store.js:1198
at memoized (ngrx-store.js:1039)
at defaultStateFn (ngrx-store.js:1079)
at ngrx-store.js:1207
at memoized (ngrx-store.js:1039)
at ngrx-store.js:1078
at Array.map (<anonymous>)
组件
ngOnInit() {
this.initializeforModel();
//this.users$ = this.store.select(getAllUsers);
this.store.select(getAllUsers).pipe().subscribe((response:any)=> {
this.listofUser = response.users;
this.userMange = this._createGroup();
});
选择器
export const userFeatureSelector = createFeatureSelector<UserState>('users');
export const getAllUsers = createSelector(
userFeatureSelector,selectAll,selectIds
);
服务
constructor(private http: HttpClient) { }
getAllUsers(): Observable<any> {
return this.http.get("assets/user.json");
}
}
减速器
import { EntityState,EntityAdapter,createEntityAdapter } from '@ngrx/entity';
export interface UserState extends EntityState<User> {
usersLoaded: boolean;
}
export const adapter: EntityAdapter<User> = createEntityAdapter<User>();
export const initialState = adapter.getinitialState({
usersLoaded: false,users: [
],});
export interface UserState {
users: User[];
}
export const userReducer = createReducer(
initialState,on(UserActions.loadUsers,(state,{ users }) => {
return adapter.setAll(users,state);
}),
动作
export const loadUsers = createAction(
'[Users List] Load Users via Service',props<{ users: User[] }>()
);
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),mergeMap(() => this.UserService.getAllUsers()
.pipe(
map(users => ({ type: UserActions.loadUsers.type,payload: users }))
// map(users => { {console.log(users)} return UserActions.usersLoaded({users})})()
))
)
);
解决方法
你不会错过选择器的返回值吗?而且, effect 应该返回一个你似乎不是的动作。你不也在那里得到一些错误吗?如果您不想要它,请将 URL
添加为 { dispatch: false}
函数的第二个参数。
createEffect()
编辑: 尝试从效果中分派一个动作或将其标记为不分派的效果
export const getAllUsers = createSelector(
userFeatureSelector,selectAll,selectIds
(feature,all,ids) => ({ feature,ids }) // In VS Code selector is underlined as faulty without this
);
我不经常使用 NgRx 实体/数据,所以我不确定它是如何工作的,但一般来说,reducer 在效果之前发生。因此,如果您希望在 loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),mergeMap(() => this.UserService.getAllUsers()
.pipe(
map(users => ({ type: UserActions.loadUsers.type,payload: users }))
))
),//map(mappedUsers => this.store.dispatch(UserActions.saveUser({mappedUsers}))) // - Either dispatch an action to save mapped users
{ dispatch: false} // or add this param so that this effect does not need to dispatch new action
);
减速器中包含应该来自 BE 的数据,那么您就错了。它实际上应该是一个没有减速器的动作,如果 BE 调用成功,你可以分派具有减速器的新动作(如 `saveUsers),这个动作将保存你的数据。
编辑 2:
我想我明白你想要达到的目标。您希望修改 loadUsers
操作的有效负载有效,对吗?试试这个方法:
loadUsers
如果我理解正确,错误来自 NgRx 实体,它的发生是因为 // actions
export const loadUsers = createAction('[Users List] Load Users via Service'); // empty
export const saveUsers = createAction('[Users Effect] Save Users',props<{ users: User[] }>());
// reducer
on(UserActions.saveUsers,(state,{ users }) => {
return adapter.setAll(users,state);
}),// effects
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),concatMap(() => this.UserService.getAllUsers()),map(users => UserActions.saveUsers({ users }))
));
的减速器具有未定义的有效负载。您试图在效果中所做的实际上并不是更新有效负载,因为效果仅在减速器之后发生。
你需要像这样从 rxjs/operators 导入 Effects 中的贴图。
import { map,mergeMap,catchError } from "rxjs/operators";
,我无法重现您遇到的确切错误,但能够让商店正常工作。
简单的商店结构如下
- 调度一个动作
在这里,我将您最初分派的操作更改为没有负载的操作
现在在我的动作文件中我创建了两个动作
import { createAction,props } from "@ngrx/store";
import { User } from "../reducers/user.reducer";
export const loadUsers = createAction(
"[Users List] Load Users"
);
export const loadUsersSuccess = createAction(
"[Users List] Load Users Success",props<{ users: User[] }>()
);
在组件中我们会有
this.store.dispatch(loadUsers());
- Effect 接收动作并发送另一个动作
在我们 dispatch 一个 action 后,effect 会收到这个 action。我们将需要调用该服务,一旦我们收到数据,就会发送一个带有有效载荷的新动作
@Injectable()
export class UserEffects {
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),mergeMap(() => this.UserService.getAllUsers()),map(users => UserActions.loadUsersSuccess({users}))
)
);
constructor(private actions$: Actions,private UserService: MyService) {}
}
- Reducer 接收到 action 并将数据保存在 store 中
export const userReducer = createReducer(
initialState,on(UserActions.loadUsers,state => {
return adapter.setAll(state.users,state);
}),on(UserActions.loadUsersSuccess,{ users }) => {
return adapter.setAll(users,state);
})
);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。