Effects help you run extra code when something happens in your app, like loading data or saving info. They keep your app organized by handling these side tasks outside your main code.
Effects for side effects in Angular
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
Angular
import { createEffect, ofType, Actions } from '@ngrx/effects'; import { Injectable } from '@angular/core'; import { map, mergeMap, catchError } from 'rxjs/operators'; import { of } from 'rxjs'; @Injectable() export class MyEffects { myEffect$ = createEffect(() => this.actions$.pipe( ofType('ACTION_TYPE'), mergeMap(() => someServiceCall().pipe( map(data => ({ type: 'SUCCESS_ACTION', payload: data })), catchError(() => of({ type: 'FAILURE_ACTION' })) ) ) ) ); constructor(private actions$: Actions) {} }
createEffect defines a side effect that listens to actions and can dispatch new actions.
ofType filters actions by their type so the effect reacts only to specific actions.
Examples
Angular
myEffect$ = createEffect(() => this.actions$.pipe( ofType('LOAD_DATA'), mergeMap(() => fetchDataFromApi().pipe( map(data => ({ type: 'LOAD_DATA_SUCCESS', payload: data })), catchError(() => of({ type: 'LOAD_DATA_FAILURE' })) )) ) );
Angular
logEffect$ = createEffect(() => this.actions$.pipe( ofType('USER_CLICK'), map(action => { console.log('User clicked:', action); return { type: 'LOGGED_CLICK' }; }) ) );
Angular
noDispatchEffect$ = createEffect(() => this.actions$.pipe( ofType('SHOW_ALERT'), map(() => { alert('Alert shown!'); }) ), { dispatch: false } );
Sample Program
This example shows an effect that listens for 'LOAD_FRUITS' action, fetches fruit data, and dispatches a success action with the fruit list.
Angular
import { Injectable } from '@angular/core'; import { createEffect, ofType, Actions } from '@ngrx/effects'; import { map, mergeMap, catchError } from 'rxjs/operators'; import { of } from 'rxjs'; // Simulated service that returns data function fetchDataFromApi() { return of(['apple', 'banana', 'cherry']); } @Injectable() export class FruitEffects { loadFruits$ = createEffect(() => this.actions$.pipe( ofType('LOAD_FRUITS'), mergeMap(() => fetchDataFromApi().pipe( map(fruits => ({ type: 'LOAD_FRUITS_SUCCESS', payload: fruits })), catchError(() => of({ type: 'LOAD_FRUITS_FAILURE' })) ) ) ) ); constructor(private actions$: Actions) {} } const actions$ = of({ type: 'LOAD_FRUITS' }); const effects = new FruitEffects(actions$); effects.loadFruits$.subscribe(action => console.log(JSON.stringify(action)));
Important Notes
Effects run outside your components to keep UI code clean and focused.
Always handle errors in effects to avoid app crashes.
Use dispatch: false if your effect does not send new actions.
Summary
Effects handle side tasks like data loading or logging outside components.
They listen for actions and can dispatch new actions based on results.
Use effects to keep your app organized and responsive.
Practice
1. What is the main purpose of
Effects in Angular applications?easy
Solution
Step 1: Understand the role of Effects
Effects are designed to handle side effects such as data fetching or logging, which are tasks outside the component's direct responsibilities.Step 2: Compare with other options
Styling, template management, and routing are handled by other Angular features, not Effects.Final Answer:
To handle side tasks like data fetching or logging outside components -> Option CQuick Check:
Effects = side tasks handler [OK]
Hint: Effects manage side tasks outside components [OK]
Common Mistakes:
- Confusing Effects with component styling
- Thinking Effects manage routing
- Assuming Effects handle templates
2. Which of the following is the correct way to create an effect using Angular's
createEffect function?easy
Solution
Step 1: Check the syntax of createEffect
ThecreateEffectfunction expects a function returning an observable, so it should be() => this.actions$.pipe(...).Step 2: Verify operators used
UsingswitchMapis correct for side effects that return new observables. const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), switchMap(() => fetchData()))); uses this correctly.Final Answer:
const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), switchMap(() => fetchData()))); -> Option BQuick Check:
createEffect needs a function returning observable [OK]
Hint: createEffect needs a function returning an observable [OK]
Common Mistakes:
- Passing observable directly instead of a function
- Using map instead of switchMap for async calls
- Not returning the observable inside createEffect
3. Given this effect code snippet:
What happens when the
loadData$ = createEffect(() => this.actions$.pipe(
ofType(loadData),
switchMap(() => this.api.getData()),
map(data => loadDataSuccess({ data })),
catchError(() => of(loadDataFailure()))
));What happens when the
loadData action is dispatched?medium
Solution
Step 1: Understand the effect flow
WhenloadDataaction is dispatched, the effect listens and triggers the API call viaswitchMap.Step 2: Analyze success and error handling
On success,mapdispatchesloadDataSuccesswith data; on error,catchErrordispatchesloadDataFailure.Final Answer:
The API call is made, and on success,loadDataSuccessaction is dispatched -> Option DQuick Check:
Effect triggers API and dispatches success or failure [OK]
Hint: Effects dispatch success or failure actions after API calls [OK]
Common Mistakes:
- Assuming no action is dispatched after API call
- Confusing map with catchError behavior
- Thinking effect causes syntax error
4. Identify the error in this effect code:
saveData$ = createEffect(() => this.actions$.pipe(
ofType(saveData),
switchMap(action => this.api.save(action.payload)),
map(() => saveDataSuccess()),
catchError(error => saveDataFailure({ error }))
));medium
Solution
Step 1: Check catchError usage
ThecatchErroroperator must return an observable, but here it returns an action object directly.Step 2: Correct catchError return
Wrapping the action inof()makes it an observable, fixing the error.Final Answer:
ThecatchErroroperator should return an observable -> Option AQuick Check:
catchError must return observable [OK]
Hint: Always wrap catchError return in of() to return observable [OK]
Common Mistakes:
- Returning plain object instead of observable in catchError
- Misusing switchMap parameters
- Thinking map must return original action
5. You want to create an effect that listens for
login actions, calls an API to authenticate, and then dispatches either loginSuccess or loginFailure. Additionally, you want to log every login attempt regardless of success or failure. Which approach correctly implements this using Angular Effects?hard
Solution
Step 1: Separate concerns for side effects
Logging is a side effect that does not dispatch actions, so it should be in a separate effect withdispatch: false.Step 2: API call effect dispatches success or failure
The main effect handles the API call and dispatchesloginSuccessorloginFailureaccordingly.Step 3: Final design
Two effects keep code clean and responsibilities clear: one for API calls with dispatch, one for logging without dispatch.Final Answer:
Use two separate effects: one for API call with dispatch, another for logging with dispatch: false -> Option AQuick Check:
Separate effects for dispatching and logging [OK]
Hint: Use separate effects for dispatching and non-dispatching tasks [OK]
Common Mistakes:
- Combining logging and dispatching in one effect incorrectly
- Using map instead of switchMap for API calls
- Forgetting dispatch: false for logging effect
