如果我有一个使用延迟加载的应用程序,并且还使用ngrx来管理状态,则每个功能的状态实例都有其自己的reducer,action等。因此,例如:
product-feature
product-edit
product-add
product-admin
state
product.reducer.ts
product.actions.ts
product.effects.ts
product.index.ts
customer-feature
customer-edit
customer-add
customer-admin
state
customer.reducer.ts
customer.actions.ts
customer.effects.ts
customer.index.ts
Run Code Online (Sandbox Code Playgroud)
通过这种结构,我的主要问题是之间的状态是否可以product-feature通信并使用之间的状态customer-feature?如果我作为用户进入customer-feature,但是customer-feature需要从中获取一些状态信息product-feature,即使product-feature由于用户没有去创建(由于延迟加载)而从未创建,它仍会渲染并获取数据吗?
我在网上看到的大多数示例都将ngrx视为一体,AppState并且不进行延迟加载,而在惰性加载示例中,组件之间的通信是父级/子级。我读过的一些文章说,您需要扩展应用程序状态以包括功能状态,因为无法在应用程序状态中引用功能状态。我想知道的实例正在兄弟功能之间传递状态。ngrx是否可以通过延迟加载来实现?
谢谢。
在我用Angular开发的应用程序中,我使用Firebase Authentication服务进行身份验证,在我的应用程序登录时,状态以正确的方式更改,根据我的需要保持表单的所有状态。
当我登录时,我在Redux DevTools中注意到我的应用程序的"auth"状态具有身份验证状态,因此我可以从经过身份验证的用户访问数据。
当我导航到系统上的任何其他页面时,"auth"身份验证状态在发生调用的事件后消失,"@ngrx/store/update-reducers"并且我的系统上不再有身份验证状态信息。
为什么会发生这种情况?为什么会"@ngrx/store/update-reducers"被调用?
我有一个"store"位于"src/app"树内文件夹中的文件。在这个文件中,我有我在根模块中创建的所有减速器"app.module"。
索引.ts:
import { ActionReducerMap, createFeatureSelector } from '@ngrx/store';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Params } from '@angular/router';
import * as fromRouter from '@ngrx/router-store';
import * as fromAuth from '../reducers/auth.reducer';
import * as fromMessenger from '../reducers/messenger.reducer';
export interface RouterStateUrl {
url: string;
queryParams: Params;
params: Params;
}
export interface StateApp {
auth: fromAuth.AuthState; …Run Code Online (Sandbox Code Playgroud) 我目前正在规划一个大规模的 Angular 6 应用程序,并试图找到一种最适合团队需求的方法来处理副作用。
我意识到在 Ngrx 生态系统中最常用的方法是使用ngrx/effects库,我想知道与thunk方法相比使用它有什么优势,thunk方法似乎是 React 最流行的方法应用。
我的想法是将所有引起副作用的逻辑隔离在一个地方,我总是倾向于将它们隔离在 Action Creators 范围内。将所有副作用逻辑移动到不同的“抽象层”感觉就像会增加编写副作用动作的开销,而没有可观的附加值,因为大多数“强烈逻辑”动作用于处理副作用。
有没有其他理由支持效果而不是 thunk?Angular 中的 ngrx 和 React 的经典 Redux 之间有什么根本区别,这使得 ngrx/effect 成为更好的选择吗?
我正在尝试@Effect()为我的操作创建一个。当我使用 type 运行 action 时,AuthenticationUserLoad出现错误。
ERROR Error: Effect "AuthenticationEffects.getUser$" dispatched an invalid action: [object Object]
Run Code Online (Sandbox Code Playgroud)
这是我的Effect代码
@Effect()
getUser$ = this.actions$.pipe(
ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
map((action) => {
return this.authService.getUser().pipe(
map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))
);
})
);
Run Code Online (Sandbox Code Playgroud)
更新
我改变map了switchMap,它的工作原理。
@Effect()
getUser$ = this.actions$.pipe(
ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
switchMap((action) => {
return this.authService.getUser().pipe(
map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))
);
})
);
Run Code Online (Sandbox Code Playgroud)
也许我不明白 map 和 switchMap 之间的区别。
我有一个称为动物的功能减速器(切片减速器)。我想将这些减速器拆分为哺乳动物、鸟类、鱼类等。这部分很简单,因为我可以简单地使用ActionReducerMap.
现在假设哺乳动物的减速器状态很大,我想将其拆分为几个较小的减速器,即猫的家庭、狗的家庭等。 ActionReducerMap 不返回减速器并且不可嵌套。我尝试在网上搜索解决方案或示例,但找不到。简而言之,我的问题是如何制作多级嵌套减速器。
export interface AnimalsState{
mammals: fromMammals.mammalsState;
birds: fromBirds.birdsState;
}
export const reducers: ActionReducerMap<AnimalsState> = {
mammals: fromMammals.reducer,
birds: fromBirds.reducer
};
Run Code Online (Sandbox Code Playgroud)
我想将哺乳动物减速器拆分为更小的减速器。
我有一组项目,我想在每个元素上进行 HTTP 调用,等待它完成,然后再进行一次调用,一次只调用一个。
我试过:
index(item) {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}
async processArray(array) {
const promises = array.map(item => this.index(item));
await Promise.all(promises);
}
proccessArray(array);
Run Code Online (Sandbox Code Playgroud)
还有 NGRX 效果:
@Effect()
effect$ = this.actions$.pipe(
ofType<action>(actionTypes.action),
mergeMapTo(this.store.select(getMyArray)),
flatMap((request: any[]) => {
return zip(...request.map(item => {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}))
}),
);
Run Code Online (Sandbox Code Playgroud)
也试着做它for …
使用 Angular 和 ngrx,我想导航到路线并确保 ngrx/store 中提供所需的数据。我正在使用 ngrx/store action/effect/reducer 来物理调用 API。路由正在加载的组件通过存储访问数据,因为系统的其他部分可能会更新数据。
如果数据加载失败,则会调度 LOAD_FAILED 操作,可以通过多种方式处理该操作。
我应该使用守卫还是解析器?每种方法还有哪些其他优点和缺点?你尝试过什么,如果有机会再给你一次,你还会这样做吗?以下是我的一些想法。
当访问路由时,guard 的 canActivate 检查数据是否在 store 中,如果没有,则从 API 加载数据,并将其添加到 store 中。如果数据加载失败,canActivate 将返回 false(作为可观察值)。
这种方法的缺点是“加载数据不应该是警卫的责任”,但优点是如果无法加载数据,则可以阻止访问,并且路由器可以处理“未找到”的情况,两者都是都在职责范围内。
当访问该路线并且任何其他防护已允许激活时,解析器将被调用。该解析器检查数据是否在存储中,如果没有,则触发 LOAD 操作,以从 API 加载并添加到存储中。然后,一旦加载了数据,解析器就会返回一些任意数据,当组件使用存储时,这些数据会被路由/组件丢弃。如果数据加载失败,某些内容会重定向到未找到的页面
这种方法的缺点是解析器没有以传统的方式使用,例如它返回的数据被丢弃。此外,解析器在未找到时需要重定向到 404,或者 LOAD_FAILED 需要重定向。这增加了复杂性,因为有时 LOAD_FAILED 可能不应该重定向,例如当后台操作触发加载时。从好的方面来说,解析器负责加载数据。
我正在学习一些ngrx教程,我想我已经开始集中注意力了。
我不明白的是如何做一些简单的事情,例如从以下位置获取值Store:
目标:无需亲自去商店就能获得价值subscribe。即:store.myStoreProperty或store.getValue(<selector>)或?
据我了解,从商店获取价值的唯一方法是执行以下操作:
private readonly _store: Store<ApplicationState>;
// ...
this._store.select(state => state.currentUser).subscribe(user => {
if (!user) { return; }
// ...
});
Run Code Online (Sandbox Code Playgroud)
问题:是否有任何可能的方法可以“立即”从商店获取值而无需订阅?
我可能只是很难理解选择器,但我认为这就是它们的用途。文档中的示例:
import { createSelector } from '@ngrx/store';
export interface FeatureState {
counter: number;
}
export interface AppState {
feature: FeatureState;
}
export const selectFeature = (state: AppState) => state.feature;
export const selectFeatureCount = createSelector(
selectFeature,
(state: FeatureState) => state.counter
);
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我想我可以直接调用selectFeature …
我有这样的问题
无法添加属性 X,对象不可扩展
在使用 Ngrx 更新将我的 angular 项目更新为 angular 9 之后。当我将 Ngrxversion 回滚到 8 时,它工作正常。但是我还需要使用 angular 9 更新将其更新到 v9。当我将其作为 datasource.data 添加到具有附加属性的材料表中时,就会发生这种情况。我认为额外的属性改变是一个原因。但是我通过使用切片从我们得到并尝试的内容创建了新数组,如下所示。
myDataArray.slice(0)
Run Code Online (Sandbox Code Playgroud)
它也不起作用。
我在这里参考了 Ngrx 版本 8 到 9 的更改列表和迁移指南https://ngrx.io/guide/migration/v9
我发现有一个与 angular 9 的不变性相关的特殊变化。他们在那里定义了动作、状态和可序列化相关的不变性逻辑。我尝试了他们建议的解决 Ngrx V9 更新问题的方法https://ngrx.io/guide/store/configuration/runtime-checks
但这些对我不起作用。如果有人对此问题有解决方案,这真的很有帮助。提前致谢..
错误堆栈跟踪..(我也使用了 matDataFlatner 这就是对象突变发生的地方)
app-error-handler.ts:30 TypeError:无法添加属性级别,对象不可扩展在 MatTreeFlattener.defaultFlattenerTransform [as transformFunction] (tree-table-flattener-builder.ts:57) at MatTreeFlattener._flattenNode (flat-data- source.ts:58) at flat-data-source.ts:81 at Array.forEach () at MatTreeFlattener._flattenChildren (flat-data-source.ts:78) at MatTreeFlattener._flattenNode (flat-data-source.ts: 65) at flat-data-source.ts:92 at Array.forEach () at MatTreeFlattener.flattenNodes (flat-data-source.ts:92) at MatTreeFlatDataSource.set (flat-data-source.ts:138)
我想创建一个 NgRx 动作创建器工厂。但我不知道如何将泛型类型传递给该props方法。
import { createAction, props } from "@ngrx/store";
function actionFactory<T>(name: string) {
return createAction(name, props<T>());
// ^^^^^^^^^^
}
Run Code Online (Sandbox Code Playgroud)
它抛出这个错误
Type 'Props<T>' provides no match for the signature '(...args: any[]): object'
Run Code Online (Sandbox Code Playgroud)
我需要如何修改工厂方法才能将泛型类型传递给props这样的方法?:
Type 'Props<T>' provides no match for the signature '(...args: any[]): object'
Run Code Online (Sandbox Code Playgroud)
你可以在Stackblitz上亲自尝试一下
ngrx ×10
angular ×8
redux ×4
typescript ×4
javascript ×2
ngrx-effects ×2
ngrx-store ×2
rxjs ×2
angular9 ×1
firebase ×1
lazy-loading ×1
redux-thunk ×1