angular - NGXS:如何在 meta-reducer 中使用 Store 或 set State
问题描述
我需要从 meta-reducer 或插件中调度一个动作。将此提供程序添加到应用程序模块时出现以下错误:
{
provide: NGXS_PLUGINS,
useFactory: myfunction,
deps: [Store],
multi: true
}
无法实例化循环依赖!InternalStateOperations ("[ERROR ->]"):在 NgModule AppModule 中
无法实例化循环依赖!StateFactory ("[ERROR ->]"): 在 NgModule AppModule 中
正确的方法是什么?
元减速器是:
export function extendApplication(store: Store) {
return function extendApplication(state, action, next) {
if (state.user.loggedIn){
if (getActionTypeFromInstance(action) !== LogoutUser.type) {
here is where I want to set a timer and if no other actions
occur before the timer expires I want to dispatch a logout action
return next(state, action);
}
}else{
return next(state, action);
}}
该模块具有上述提供者。
解决方案
MetaReducers 可以通过函数或服务(类)来实现。
如果你通过一个函数来实现它,你可以这样做:
import { NgModule } from '@angular/core';
import { NGXS_PLUGINS } from '@ngxs/store';
import { getActionTypeFromInstance } from '@ngxs/store';
@NgModule({
imports: [NgxsModule.forRoot([])],
providers: [
{
provide: NGXS_PLUGINS,
useValue: logoutPlugin,
multi: true
}
]
})
export class AppModule {}
export function logoutPlugin(state, action, next) {
// Use the get action type helper to determine the type
if (getActionTypeFromInstance(action) === Logout.type) {
// if we are a logout type, lets erase all the state
state = {};
}
// return the next function with the empty state
return next(state, action);
}
仅通过更新传递给函数的state
对象并将其传递回返回的next
函数来改变状态。
您可以在插件中注入 Store,使用Injector
和获取实例,但您不能在插件内调度动作,因为您将创建一个无限循环。
如果你想通过服务来实现它,你可以这样做:
import {
NGXS_PLUGINS,
NgxsModule,
ActionType,
NgxsNextPluginFn,
NgxsPlugin
} from "@ngxs/store";
import { Injectable, Inject, Injector } from '@angular/core';
@NgModule({
imports: [
NgxsModule.forRoot([TestState]),
],
providers: [
{
provide: NGXS_PLUGINS,
useClass: TestInterceptor,
multi: true
}
]
})
export class AppModule {}
@Injectable()
export class TestInterceptor implements NgxsPlugin {
constructor(
private _injector: Injector
){
}
public handle(
state,
action: ActionType,
next: NgxsNextPluginFn
): NgxsNextPluginFn {
const matches: (action: ActionType) => boolean = actionMatcher(action);
const isInitialAction: boolean = matches(InitState) || matches(UpdateState);
// you can validate the action executed matches the one you are hooking into
// and update state accordingly
// state represents full state obj, if you need to update a specific state,
// you need to use the `name` from the @State definition
state = { test: ["state mutated in plugin"] };
// get store instance via Injector
const store = this._injector.get<Store>(Store);
return next(state, action);
}
}
如果您想查看它,我还创建了stackblitz示例
推荐阅读
- r - 从右向左剪切一个字符串,直到遇到某个字符 R
- xcode - 如何修复 Xcode 问题 BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Debug
- php - 如果用户从单个类别购买“x”产品,则提供免费送货服务
- javascript - Firebase 存储任务(进度条)
- python - 如何从 pandas 的同一个数据框在 seaborn 中制作两个单独的图?
- google-apps-script - 从另一个谷歌工作表范围填充的下拉列表
- sql - 使用 WHERE 子句代替聚合函数的逻辑
- javascript - 尝试导入错误:“showErrorMessage”未从“../helpers/alerts”导出
- python - 如何漂亮地打印字典列表
- amazon-web-services - 如何在没有标准 ssh 的情况下将 AWS 实例连接到 GCP 实例