我正在尝试将现有的应用程序从ngrx v2迁移到v4,并且我在migration document中没有看到的情况遇到一些麻烦。迁移文档可以删除@ngrx / core,但我不知道如何处理从@ ngrx / core / add / operator / select导入的reducers并从Observable中选择。我收到错误" Property' select'类型' Observable'"不存在来自所有减速器。
/actions/action-with-payload.ts - 迁移的解决方法
import { Action } from '@ngrx/store';
export class ActionWithPayload implements Action {
type: string;
payload?: any;
}
/actions/users-list.ts
export class UsersListActions {
static LOAD_USERS_LIST = '[UserManagement/Users List] Load Users List';
loadUsersList(): ActionWithPayload {
return {
type: UsersListActions.LOAD_USERS_LIST
};
}
static LOAD_USERS_LIST_SUCCESS = '[UserManagement/Users List] Load Users List Success';
loadUsersListSuccess(users: User[]): ActionWithPayload {
return {
type: UsersListActions.LOAD_USERS_LIST_SUCCESS,
payload: users
};
}
}
/reducers/users-list.ts
export interface UsersListState {
loaded: boolean;
loading: boolean;
entities: User[];
}
const initialState: UsersListState = {
loaded: false,
loading: false,
entities: [],
}
export default function (state = initialState, action: ActionWithPayload): UsersListState {
switch (action.type) {
case UsersListActions.LOAD_USERS_LIST:
return Object.assign({}, state, {
loading: true
});
case UsersListActions.LOAD_USERS_LIST_SUCCESS:
return Object.assign({}, state, {
loaded: true,
loading: false,
entities: action.payload
});
default:
return state;
}
};
export function getLoaded() {
return (state$: Observable<UsersListState>) => state$
.select(s => s.loaded);
}
export function getLoading() {
return (state$: Observable<UsersListState>) => state$
.select(s => s.loading);
}
export function getUsers() {
return (state$: Observable<UsersListState>) => state$
.select(s => s.entities);
}
/reducers/index.ts
import usersListReducer, * as fromUsers from './users-list';
export interface UserManagementState {
usersList: fromUsers.UsersListState,
};
export { usersListReducer }
export function getUsersListState() {
return (state$: Observable<UserManagementState>) => state$
.select(s => s.usersList);
}
export function getUsers() {
return compose(fromUsers.getUsers(), getUsersListState());
}
export function getUsersLoaded() {
return compose(fromUsers.getLoaded(), getUsersListState());
}
export function getUsersLoading() {
return compose(fromUsers.getLoading(), getUsersListState());
}
/pages/user-list.page.ts
export class UserListPage {
private users$: Observable<User[]>;
private usersLoading$: Observable<boolean>;
constructor(
private store: Store<UserManagementState>,
) {
this.users$ = store.let(getUsers());
this.usersLoading$ = store.let(getUsersLoading());
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { usersListReducer } from '/reducers';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
SharedModule.forRoot(),
StoreModule.provideStore({
usersList: usersListReducer,
...
})
],
declarations: [AppComponent],
bootstrap: [AppComponent],
providers: [
...
]
})
export class AppModule { }
答案 0 :(得分:1)
我不确定您为什么需要导入select
。即使在版本2中,我也从未这样做过。我将尝试展示代码对于单个实体应该是什么样子。
import {
Action,
ActionReducerMap,
createFeatureSelector,
createSelector
} from '@ngrx/store';
export function userReducer(state = initialState, action: ActionWithPayload): UsersListState {
switch (action.type) {
case UsersListActions.LOAD_USERS_LIST:
return Object.assign({}, state, {
loading: true
});
case UsersListActions.LOAD_USERS_LIST_SUCCESS:
return Object.assign({}, state, {
loaded: true,
loading: false,
entities: action.payload
});
default:
return state;
}
};
export const getLoadedState = (state: UsersListState) => state.loaded;
export const getLoadingState = (state: UsersListState) => state.loading;
export const getEntitiesState = (state: UsersListState) => state.entities;
export userStateSelector = createFeatureSelector<UsersListState>('users');
export const loadedState = createSelector(userStateSelector, getLoadedState);
export const loadingState = createSelector(userStateSelector, getLoadingState);
export const userState = createSelector(userStateSelector, getEntitiesState);
模块
imports: StoreModule.forFeature('users', userReducer);
在组件使用中选择如下:
public users$: Observable<User[]>;
constructor(private userStore: Store<UsersListState>){
this.users$ = this.userStore.select(userState);
}
可能存在很多编译错误,但这只是一个伪代码来解释你的工作原理。
您可以查看https://github.com/ngrx/platform/tree/master/example-app以获取详细示例。但就我个人而言,我很难理解它是如何运作的。如果你有兴趣的话,我本周末可能会写一篇博客。
答案 1 :(得分:0)
创建一个包含所有状态的接口,如下所示,
export interface CompanyAppStore {
userState: UsersListState;
employeeState: EmployesListState;
}
创建一个reducer工厂,它是所有Reducer的集合,如下所示
export const reducers: ActionReducerMap<CompanyAppStore> = {
userState: userStateReducer.reducer,
employeeState: employeeStateReducer.reducer
};
按以下方式导入减速器,
import * as userStateReducer from './user.state.reducer';
import * as employeeStateReducer from './employee.state.reducer';
您的组件可以使用在步骤1中创建的应用程序界面注入
constructor(private appStore: Store<CompanyAppStore>){ }
现在您可以使用
选择特定的州this.appStore
.select(states => states.userState)
.subscribe(..)