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
и получив экземпляр, но вы не можете отправить действие внутри плагина, потому что вы создадите бесконечное l oop.
Если вы хотите реализовать его через Сервис, вы можете сделать:
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 пример, если вы хотите проверить его