What is @ngrx/effects?
@ngrx/effects is a library for managing side effects in Angular applications using the Redux pattern. It allows you to isolate side effects from your components and services, making your code more predictable and easier to test.
What are @ngrx/effects's main functionalities?
Handling Side Effects
This code demonstrates how to handle side effects using @ngrx/effects. The `loadItems$` effect listens for the `loadItems` action, calls a service to fetch data, and then dispatches either a success or failure action based on the result.
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { MyService } from './my-service';
import * as MyActions from './my-actions';
@Injectable()
export class MyEffects {
loadItems$ = createEffect(() => this.actions$.pipe(
ofType(MyActions.loadItems),
mergeMap(() => this.myService.getAll().pipe(
map(items => MyActions.loadItemsSuccess({ items })),
catchError(() => of(MyActions.loadItemsFailure()))
))
));
constructor(
private actions$: Actions,
private myService: MyService
) {}
}
Combining Multiple Effects
This code demonstrates how to combine multiple effects in a single class. The `loadItems$` effect handles loading items, while the `updateItem$` effect handles updating an item. Both effects listen for their respective actions and call the appropriate service methods.
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { MyService } from './my-service';
import * as MyActions from './my-actions';
@Injectable()
export class MyEffects {
loadItems$ = createEffect(() => this.actions$.pipe(
ofType(MyActions.loadItems),
mergeMap(() => this.myService.getAll().pipe(
map(items => MyActions.loadItemsSuccess({ items })),
catchError(() => of(MyActions.loadItemsFailure()))
))
));
updateItem$ = createEffect(() => this.actions$.pipe(
ofType(MyActions.updateItem),
mergeMap(action => this.myService.update(action.item).pipe(
map(() => MyActions.updateItemSuccess({ item: action.item })),
catchError(() => of(MyActions.updateItemFailure()))
))
));
constructor(
private actions$: Actions,
private myService: MyService
) {}
}
Error Handling
This code demonstrates how to handle errors in effects. The `loadItems$` effect catches any errors that occur during the service call and dispatches a `loadItemsFailure` action with the error information.
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { MyService } from './my-service';
import * as MyActions from './my-actions';
@Injectable()
export class MyEffects {
loadItems$ = createEffect(() => this.actions$.pipe(
ofType(MyActions.loadItems),
mergeMap(() => this.myService.getAll().pipe(
map(items => MyActions.loadItemsSuccess({ items })),
catchError(error => of(MyActions.loadItemsFailure({ error })))
))
));
constructor(
private actions$: Actions,
private myService: MyService
) {}
}
Other packages similar to @ngrx/effects
redux-saga
redux-saga is a library that aims to make side effects (e.g., asynchronous actions like data fetching) easier and more manageable in Redux applications. It uses generator functions to handle side effects, which can make the code more readable and easier to test compared to @ngrx/effects.
redux-thunk
redux-thunk is a middleware that allows you to write action creators that return a function instead of an action. This function can then perform asynchronous dispatches. While simpler than @ngrx/effects, it can become harder to manage as the complexity of side effects grows.
mobx
MobX is a state management library that makes it simple to connect the reactive data of your application with the UI. Unlike @ngrx/effects, MobX uses observables to manage state and side effects, which can be more intuitive for some developers.
5.0.0 (2018-01-22)
Bug Fixes
- Effects: Ensure Store modules are loaded eagerly (#658) (0a3398d), closes #642
- Effects: Remove toPayload utility function (#738) (b390ef5)
- Entity: updateOne/updateMany should not change ids state on existing entity (#581) (b989e4b), closes #571
- RouterStore: Fix usage of config object if provided (#575) (4125914)
- RouterStore: Match RouterAction type parameters (#562) (980a653)
- Schematics: Add group folder after feature name folder (#737) (317fb94)
- Schematics: Add handling of flat option to entity blueprint (fb8d2c6)
- Schematics: Distinguish between root and feature effect arrays when registering (#718) (95ff6c8)
- Schematics: Don't add state import if not provided (#697) (e5c2aed)
- Schematics: Make variable naming consistent for entity blueprint (#716) (765b15a)
- Store: Compose provided metareducers for a feature reducer (#704) (1454620), closes #701
- StoreDevtools: Only recompute current state when reducers are updated (#570) (247ae1a), closes #229 #487
- typo: update login error to use correct css font color property (41723fc)
Features
- Effects: Add lettable ofType operator (d5e1814)
- ErrorHandler: Use the Angular ErrorHandler for reporting errors (#667) (8f297d1), closes #626
- material: Upgrade @angular/material to v 2.0.0-beta.12 (#482) (aedf20e), closes #448
- Schematics: Add alias for container, store and action blueprints (#685) (dc64ac9)
- Schematics: Add alias for reducer blueprint (#684) (ea98fb7)
- Schematics: Add effect to registered effects array (#717) (f1082fe)
- Schematics: Add option to group feature blueprints in respective folders (#736) (b82c35d)
- Schematics: Introduce @ngrx/schematics (#631) (1837dba), closes #53
- Store: Add lettable select operator (77eed24)
- Store: Add support for generating custom createSelector functions (#734) (cb0d185), closes #478 #724
- StoreDevtools: Add option to configure extension in log-only mode (#712) (1ecd658), closes #643 #374
- StoreDevtools: Add support for custom instance name (#517) (00be3d1), closes #463
- StoreDevtools: Add support for extension sanitizers (#544) (6ed92b0), closes #494
- StoreDevtools: Add support for jumping to a specific action (#703) (b9f6442), closes #681
BREAKING CHANGES
-
Effects: The utility function toPayload
, deprecated in @ngrx/effects v4.0, has been removed.
Before:
import { toPayload } from '@ngrx/effects';
actions$.ofType('SOME_ACTION').map(toPayload);
After:
actions$.ofType('SOME_ACTION').map((action: SomeActionWithPayload) => action.payload);
-
ErrorHandler: The ErrorReporter has been replaced with ErrorHandler
from angular/core.
BEFORE:
Errors were reported to the ngrx/effects ErrorReporter. The
ErrorReporter would log to the console by default.
AFTER:
Errors are now reported to the @angular/core ErrorHandler.
- Store: Updates minimum version of RxJS dependency.
BEFORE:
Minimum peer dependency of RxJS ^5.0.0
AFTER:
Minimum peer dependency of RxJS ^5.5.0
- Effects: Updates minimum version of RxJS dependency.
BEFORE:
Minimum peer dependency of RxJS ^5.0.0
AFTER:
Minimum peer dependency of RxJS ^5.5.0
<a name="4.1.1"></a>