CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ngrx--effects

Side effect model for @ngrx/store that manages asynchronous operations and external interactions in Angular applications using RxJS

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

@ngrx/effects

NgRx Effects is a side effect model for @ngrx/store that provides RxJS-powered effect management for Angular applications. It allows for handling asynchronous operations and external interactions while maintaining separation of concerns between pure state logic and side effects.

Package Information

  • Package Name: @ngrx/effects
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @ngrx/effects

Core Imports

import {
  createEffect,
  Actions,
  ofType,
  EffectsModule,
  provideEffects,
  mergeEffects,
  getEffectsMetadata
} from "@ngrx/effects";

Basic Usage

import { Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { map, switchMap } from "rxjs/operators";
import { of } from "rxjs";

@Injectable()
export class UserEffects {
  constructor(private actions$: Actions) {}

  // Class-based effect
  loadUsers$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UserActions.loadUsers),
      switchMap(() =>
        this.userService.getUsers().pipe(
          map(users => UserActions.loadUsersSuccess({ users })),
          catchError(error => of(UserActions.loadUsersFailure({ error })))
        )
      )
    )
  );
}

// Functional effect
export const loadUsersEffect = createEffect(
  (actions$ = inject(Actions)) =>
    actions$.pipe(
      ofType(UserActions.loadUsers),
      switchMap(() =>
        inject(UserService).getUsers().pipe(
          map(users => UserActions.loadUsersSuccess({ users }))
        )
      )
    ),
  { functional: true }
);

Architecture

NgRx Effects is built around several key components:

  • Effect Creation: createEffect() function for defining effects with metadata
  • Action Stream: Actions service providing access to all dispatched actions
  • Action Filtering: ofType() operator for type-safe action filtering
  • Module Integration: EffectsModule for module-based setup, provideEffects() for standalone apps
  • Lifecycle Management: Hooks for controlling effect registration and execution
  • Error Handling: Built-in error handling with retry mechanisms
  • Testing Support: Mock providers and utilities for effect testing

Capabilities

Effect Creation and Management

Core functionality for creating and managing effects, including both class-based and functional patterns.

function createEffect<
  C extends EffectConfig & { functional?: false },
  DT extends DispatchType<C>,
  OTP,
  R extends EffectResult<OT>,
  OT extends ObservableType<DT, OTP>
>(
  source: () => R & ConditionallyDisallowActionCreator<DT, R>,
  config?: C
): R & CreateEffectMetadata;

function createEffect<Source extends () => Observable<unknown>>(
  source: Source,
  config: EffectConfig & { functional: true; dispatch: false }
): FunctionalEffect<Source>;

function createEffect<Source extends () => Observable<Action>>(
  source: Source & ConditionallyDisallowActionCreator<true, ReturnType<Source>>,
  config: EffectConfig & { functional: true; dispatch?: true }
): FunctionalEffect<Source>;

function createEffect<
  Result extends EffectResult<unknown>,
  Source extends () => Result
>(
  source: Source,
  config?: EffectConfig
): (Source | Result) & CreateEffectMetadata;

interface EffectConfig {
  dispatch?: boolean;
  functional?: boolean;
  useEffectsErrorHandler?: boolean;
}

type DispatchType<T> = T extends { dispatch: infer U } ? U : true;
type ObservableType<T, OriginalType> = T extends false ? OriginalType : Action;
type EffectResult<OT> = Observable<OT> | ((...args: any[]) => Observable<OT>);
type ConditionallyDisallowActionCreator<DT, Result> = DT extends false
  ? unknown
  : Result extends EffectResult<infer OT>
  ? OT extends ActionCreator
    ? 'ActionCreator cannot be dispatched. Did you forget to call the action creator function?'
    : unknown
  : unknown;

type FunctionalEffect<
  Source extends () => Observable<unknown> = () => Observable<unknown>
> = Source & FunctionalCreateEffectMetadata;

interface FunctionalCreateEffectMetadata extends CreateEffectMetadata {
  '__@ngrx/effects_create__': EffectConfig & { functional: true };
}

interface CreateEffectMetadata {
  '__@ngrx/effects_create__': EffectConfig;
}

Effect Creation and Management

Actions and Filtering

Action stream management and type-safe action filtering capabilities.

class Actions<V = Action> extends Observable<V> {
  lift<R>(operator?: Operator<V, R>): Observable<R>;
}

function ofType<E extends Extract<A, { type: T }>, A extends Action = Action, T extends string = A['type']>(
  ...allowedTypes: [T, ...T[]]
): OperatorFunction<A, E>;

function ofType<AC extends ActionCreator<string, Creator>, U extends Action = Action>(
  ...allowedTypes: [AC, ...AC[]]
): OperatorFunction<U, ReturnType<AC>>;

Actions and Filtering

Module Setup and Providers

Integration with Angular's module system and standalone applications.

class EffectsModule {
  static forRoot(effects: Type<any>[]): ModuleWithProviders<EffectsRootModule>;
  static forFeature(effects: Type<any>[]): ModuleWithProviders<EffectsFeatureModule>;
}

function provideEffects(
  effects: Array<Type<unknown> | Record<string, FunctionalEffect>>
): EnvironmentProviders;

function provideEffects(
  ...effects: Array<Type<unknown> | Record<string, FunctionalEffect>>
): EnvironmentProviders;

function mergeEffects(...effects: Array<Observable<Action> | (() => Observable<Action>)>): () => Observable<Action>;

function getEffectsMetadata<T extends Record<keyof T, Object>>(instance: T): EffectMetadata<T>[];

Module Setup and Providers

Advanced Features

Lifecycle hooks, error handling, and advanced effect management capabilities.

interface OnIdentifyEffects {
  ngrxOnIdentifyEffects(): string;
}

interface OnRunEffects {
  ngrxOnRunEffects(resolvedEffects$: Observable<EffectNotification>): Observable<EffectNotification>;
}

interface OnInitEffects {
  ngrxOnInitEffects(): Action;
}

type EffectsErrorHandler = <T extends Action>(
  observable$: Observable<T>,
  errorHandler: ErrorHandler
) => Observable<T>;

function defaultEffectsErrorHandler<T extends Action>(
  observable$: Observable<T>,
  errorHandler: ErrorHandler,
  retryAttemptLeft: number = 10
): Observable<T>;

Advanced Features

Testing Utilities

Testing support for effects with mock providers and utilities.

function provideMockActions(source: Observable<any>): FactoryProvider;
function provideMockActions(factory: () => Observable<any>): FactoryProvider;

Import testing utilities:

import { provideMockActions } from "@ngrx/effects/testing";

Testing Utilities

Core Types

interface Action {
  type: string;
}

interface ActionCreator<T extends string = string, C extends Creator = Creator> {
  readonly type: T;
  (...args: any[]): any;
}

interface Creator {
  (...args: any[]): object;
}

interface EffectNotification {
  effect: Observable<any> | (() => Observable<any>);
  propertyName: PropertyKey;
  sourceName: string | null;
  sourceInstance: any;
  notification: ObservableNotification<Action | null | undefined>;
}

interface EffectSources {
  addEffects(effectSourceInstance: any): void;
  toActions(): Observable<Action>;
}

class EffectsRunner implements OnDestroy {
  get isStarted(): boolean;
  start(): void;
  ngOnDestroy(): void;
}

interface OnDestroy {
  ngOnDestroy(): void;
}

interface ObservableNotification<T> {
  kind: 'N' | 'E' | 'C';
  value?: T;
  error?: any;
}

type EffectPropertyKey<T extends Record<keyof T, Object>> = Exclude<
  keyof T,
  keyof Object
>;

interface EffectMetadata<T extends Record<keyof T, Object>>
  extends Required<EffectConfig> {
  propertyName: EffectPropertyKey<T>;
}

type EffectsMetadata<T extends Record<keyof T, Object>> = {
  [Key in EffectPropertyKey<T>]?: EffectConfig;
};

interface Type<T = any> {
  new (...args: any[]): T;
}

interface ModuleWithProviders<T> {
  ngModule: Type<T>;
  providers?: any[];
}

interface EnvironmentProviders {
  ɵproviders: any[];
}

interface FactoryProvider {
  provide: any;
  useFactory: (...args: any[]) => any;
  deps?: any[];
}

interface InjectionToken<T> {
  toString(): string;
}

interface Observable<T> {
  pipe(...operations: any[]): Observable<any>;
  subscribe(...args: any[]): any;
}

interface OperatorFunction<T, R> {
  (source: Observable<T>): Observable<R>;
}

interface Operator<T, R> {
  call(subscriber: any, source: Observable<T>): any;
}

Constants and Tokens

const ROOT_EFFECTS_INIT: "@ngrx/effects/init";

function rootEffectsInit(): Action;

const EFFECTS_ERROR_HANDLER: InjectionToken<EffectsErrorHandler>;
const USER_PROVIDED_EFFECTS: InjectionToken<Array<Type<unknown> | InjectionToken<unknown>>[]>;
const _ROOT_EFFECTS_GUARD: InjectionToken<void>;
const _ROOT_EFFECTS: InjectionToken<[Array<Type<unknown> | Record<string, FunctionalEffect>>]>;
const _ROOT_EFFECTS_INSTANCES: InjectionToken<unknown[]>;
const _FEATURE_EFFECTS: InjectionToken<Array<Type<unknown> | Record<string, FunctionalEffect>>[]>;
const _FEATURE_EFFECTS_INSTANCE_GROUPS: InjectionToken<unknown[][]>;
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@ngrx/effects@20.0.x
Publish Source
CLI
Badge
tessl/npm-ngrx--effects badge