Angular NGXS:如何在meta reducer中使用存储或设置状态
我需要从meta reducer或插件中分派一个操作。将此提供商添加到应用程序模块时,我遇到以下错误:Angular NGXS:如何在meta reducer中使用存储或设置状态,angular,nativescript,ngxs,Angular,Nativescript,Ngxs,我需要从meta reducer或插件中分派一个操作。将此提供商添加到应用程序模块时,我遇到以下错误: { provide: NGXS_PLUGINS, useFactory: myfunction, deps: [Store], multi: true } 无法实例化循环依赖项!InternalStateOperations(“[ERROR ->]“”:在NgModule AppModule中 无法实例化循环依赖项!状态工
{
provide: NGXS_PLUGINS,
useFactory: myfunction,
deps: [Store],
multi: true
}
无法实例化循环依赖项!InternalStateOperations(“[ERROR
->]“”:在NgModule AppModule中
无法实例化循环依赖项!状态工厂(“[ERROR->]”):位于
NgModule应用模块
正确的方法是什么
meta-reducer是:
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);
}}
该模块具有上述提供程序。可以通过函数或服务(类)实现MetaReducer 如果通过函数实现,可以执行以下操作:
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);
}
只需更新传递到函数中的状态
对象并将其传递回返回的下一个
函数,状态就会发生变化
您可以使用Injector
在插件中注入存储并获取实例,但是您不能在插件中分派actiom,因为您将创建一个无限循环
如果您想通过服务实现它,可以执行以下操作:
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);
}
}
导入{
NGXS_插件,
NGXS模块,
动作类型,
NgxsNextPluginFn,
NgxsPlugin
}来自“@ngxs/store”;
从“@angular/core”导入{Injectable,injection,Injector};
@NGD模块({
进口:[
NgxsModule.forRoot([TestState]),
],
供应商:[
{
提供:NGXS_插件,
使用类别:睾丸接收器,
多:真的
}
]
})
导出类AppModule{}
@可注射()
导出类TestInterceptor实现NgxsPlugin{
建造师(
专用注射器:注射器
){
}
公共处理(
国家,,
action:ActionType,
下一个:NgxsNextPluginFn
):NgxsNextPluginFn{
常量匹配:(action:ActionType)=>boolean=actionMatcher(action);
常量isInitialAction:布尔=匹配(InitState)| |匹配(UpdateState);
//您可以验证执行的操作是否与您要挂接的操作匹配
//并相应地更新状态
//状态表示完全状态obj,如果需要更新特定状态,
//您需要使用@State定义中的'name'
state={test:[“插件中的状态突变”]};
//通过注入器获取存储实例
const store=this.\u injector.get(store);
返回下一步(状态、动作);
}
}
我还创建了一个示例,如果您想查看它的话MetaReducer可以通过函数或服务(类)实现 如果通过函数实现,可以执行以下操作:
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);
}
只需更新传递到函数中的状态
对象并将其传递回返回的下一个
函数,状态就会发生变化
您可以使用Injector
在插件中注入存储并获取实例,但是您不能在插件中分派actiom,因为您将创建一个无限循环
如果您想通过服务实现它,可以执行以下操作:
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);
}
}
导入{
NGXS_插件,
NGXS模块,
动作类型,
NgxsNextPluginFn,
NgxsPlugin
}来自“@ngxs/store”;
从“@angular/core”导入{Injectable,injection,Injector};
@NGD模块({
进口:[
NgxsModule.forRoot([TestState]),
],
供应商:[
{
提供:NGXS_插件,
使用类别:睾丸接收器,
多:真的
}
]
})
导出类AppModule{}
@可注射()
导出类TestInterceptor实现NgxsPlugin{
建造师(
专用注射器:注射器
){
}
公共处理(
国家,,
action:ActionType,
下一个:NgxsNextPluginFn
):NgxsNextPluginFn{
常量匹配:(action:ActionType)=>boolean=actionMatcher(action);
常量isInitialAction:布尔=匹配(InitState)| |匹配(UpdateState);
//您可以验证执行的操作是否与您要挂接的操作匹配
//并相应地更新状态
//状态表示完全状态obj,如果需要更新特定状态,
//您需要使用@State定义中的'name'
state={test:[“插件中的状态突变”]};
//通过注入器获取存储实例
const store=this.\u injector.get(store);
返回下一步(状态、动作);
}
}
我还创建了一个示例,如果您想查看它,请编辑:实际上,当您可以使用已经有中间件的插件时,使用中间件是没有意义的。这样,我们所要做的就是创造行动:
@Action(RequestLogout)
async requestLogout(context: StateContext<IAuthStateModel>) {
context.dispatch(new Navigate(['/login']));
context.dispatch(new StateResetAll());
}
然后在您的应用程序模块中,您必须声明LogoutMiddleware(fun-fact meta reducer只是redux中间件的别致名称)并导入NgxsResetPluginModule
providers: [
{
provide: NGXS_PLUGINS,
useClass: LogoutMiddleware,
multi: true,
},
...
],
imports: [
NgxsResetPluginModule.forRoot(),
...
],
编辑:实际上,当您可以使用已经有中间件的插件时,使用中间件是没有意义的。这样,我们所要做的就是创造行动:
@Action(RequestLogout)
async requestLogout(context: StateContext<IAuthStateModel>) {
context.dispatch(new Navigate(['/login']));
context.dispatch(new StateResetAll());
}
然后在您的应用程序模块中,您必须声明LogoutMiddleware(fun-fact meta reducer只是redux中间件的别致名称)并导入NgxsResetPluginModule
providers: [
{
provide: NGXS_PLUGINS,
useClass: LogoutMiddleware,
multi: true,
},
...
],
imports: [
NgxsResetPluginModule.forRoot(),
...
],
您将在工厂函数中收到全局状态。在您的代码片段中,存储来自何处?它位于module.ts中的import语句中:import{NgxsModule,Store,NGXS_PLUGINS}from'@NGXS/Store'@我更新了代码。现在我可以看到,我已经两次引用了这个存储——一次在模块提供程序中,另一次在extendApplication函数中。在meta reducer中获取对存储的引用的正确方法是什么?您是否尝试将其作为插件实现,以便能够将存储注入构造函数?我也这样做了,但结果相同。您将在工厂函数中收到全局状态。在您的代码片段中,存储来自何处?它位于module.ts中的import语句中:import{NgxsModule,Store,NGXS_PLUGINS}from'@NGXS/Store'@我更新了代码。现在我可以看到,我已经两次引用了这个存储——一次在模块提供程序中,另一次在extendApplication函数中。在meta reducer中获取对存储的引用的正确方法是什么?您是否尝试将其实现为插件,以便能够在