Effects

Effects can be used to execute side effects (actions, http requests and other operations) upon action events. First, install the package:

npm i @datorama/akita-ng-effects

Next, to register effects, simply run AkitaNgEffects.forRoot() and register the effect classes:

app.module.ts
import { AkitaNgEffectsModule } from '@datorama/akita-ng-effects';
import { NavigationEffects } from './path/to/effects';
// Only use .forRoot() once in your base module.
@NgModule({
imports: [CommonModule, AkitaNgEffectsModule.forRoot([NavigationEffects])],
})
export class AppModule {}
product.module.ts
import { AkitaNgEffectsModule } from '@datorama/akita-ng-effects';
import { ProductEffects } from './path/to/effects';
// Use .forFeature() on any feature module
@NgModule({
imports: [CommonModule, AkitaNgEffectsModule.forFeature([ProductEffects])],
})
export class FeatureModule {}

Setup Actions

An action always holds a type property and an optional payload.

navigation.actions.ts
import { createAction } from '@datorama/akita-ng-effects';
export const loadMainNavigation = createAction('[Navigation] Load Main Navigation');
export const loadMainNavigationSuccess = createAction(
'[Navigation] Load Main Navigation Success',
props<{ mainNav: { id: number; path: string } }>()
);

Setup Effects

You can use the actions to act upon any action event:

navigation.effect.ts
import { Actions } from '@datorama/akita-ng-effects';
@Injectable()
export class NavigationEffects {
constructor(
private actions$: Actions,
private navigationService: NavigationService,
) {}
loadMainNavigation$ = createEffect(() =>
this.actions$.pipe(
ofType(loadMainNavigation),
switchMap((_) =>
this.navigationService.loadMainNavigation().pipe(
map((mainNav) => loadMainNavigationSuccess({ mainNav }))
)
)
), { dispatch: true }
);
// Or use the decorator
@Effect()
loadMainNavigationSuccess$ = this.actions$.pipe(
ofType(loadMainNavigationSuccess),
map(({ mainNav }) => this.navigationService.updateNavigationTree(mainNav)),
tap((mainRoutes) => this.store.updateNavigation(mainRoutes))
);
}

The parameter dispatch

This parameter dictates if the effect can dispatch an action. Set true if you want the effect to dispatch an action. Set to false or omit if the effect should not dispatch any action.

Possible use case

This is one possible use case for an action inside a guard to initialize fetching of a navigation.

You can also use them in components in order to fetch data.

init-route.guard.ts
@Injectable({
providedIn: 'root',
})
export class InitRouterGuard implements CanActivate {
constructor(private actions: Actions, private navigationQuery: NavigationQuery) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
return this.navigationQuery.isNavInitialized$.pipe(
tap((isInit) => {
if (!isInit) this.actions.dispatch(loadMainNavigation());
}),
filter((isInit) => isInit),
map((_) => true)
);
}
}