Bird
Raised Fist0
Angularframework~20 mins

Effects for side effects in Angular - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
NgRx Effects Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What happens when an effect dispatches an action?

Consider an Angular effect that listens for an action and dispatches another action. What is the result in the application?

Angular
import { createEffect, ofType, Actions } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import * as MyActions from './actions';

@Injectable()
export class MyEffects {
  effect$ = createEffect(() => this.actions$.pipe(
    ofType(MyActions.loadData),
    map(() => MyActions.loadDataSuccess({ data: [1, 2, 3] }))
  ));

  constructor(private actions$: Actions) {}
}
AThe effect listens for 'loadData' action and dispatches 'loadDataSuccess' action, updating the store accordingly.
BThe effect listens for 'loadData' but does not dispatch any action, so the store remains unchanged.
CThe effect causes an infinite loop because it dispatches the same action it listens for.
DThe effect runs only once and then stops listening for actions.
Attempts:
2 left
💡 Hint

Think about what happens when an effect returns a new action.

📝 Syntax
intermediate
2:00remaining
Identify the syntax error in this effect definition

Which option shows the correct syntax for creating an effect that does NOT dispatch an action?

Angular
import { createEffect, ofType, Actions } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { tap } from 'rxjs/operators';
import * as MyActions from './actions';

@Injectable()
export class MyEffects {
  logEffect$ = createEffect(() => this.actions$.pipe(
    ofType(MyActions.loadData),
    tap(() => console.log('Load data action received'))
  ), { dispatch: false });

  constructor(private actions$: Actions) {}
}
AThe effect is missing a return statement inside createEffect.
BThe effect should use map instead of tap to dispatch an action.
CThe effect must include { dispatch: false } to avoid dispatching an action.
DThe effect should not use ofType operator.
Attempts:
2 left
💡 Hint

Think about how to create effects that only perform side effects without dispatching new actions.

🔧 Debug
advanced
2:00remaining
Why does this effect cause an infinite loop?

Examine the effect below. Why does it cause an infinite loop?

Angular
import { createEffect, ofType, Actions } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import * as MyActions from './actions';

@Injectable()
export class MyEffects {
  loopEffect$ = createEffect(() => this.actions$.pipe(
    ofType(MyActions.loadData),
    map(() => MyActions.loadData())
  ));

  constructor(private actions$: Actions) {}
}
ABecause the effect uses map instead of tap, causing a syntax error.
BBecause the effect listens for 'loadData' and dispatches the same 'loadData' action, triggering itself repeatedly.
CBecause the effect does not unsubscribe from the actions stream.
DBecause the effect is missing { dispatch: false } option.
Attempts:
2 left
💡 Hint

Think about what happens when an effect dispatches the same action it listens for.

state_output
advanced
2:00remaining
What is the state after this effect runs?

Given the reducer and effect below, what will be the state after dispatching 'loadData'?

Angular
import { createReducer, on } from '@ngrx/store';
import * as MyActions from './actions';

export interface State {
  data: number[];
  loading: boolean;
}

export const initialState: State = {
  data: [],
  loading: false
};

export const myReducer = createReducer(
  initialState,
  on(MyActions.loadData, state => ({ ...state, loading: true })),
  on(MyActions.loadDataSuccess, (state, { data }) => ({ ...state, data, loading: false }))
);

// Effect
import { createEffect, ofType, Actions } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map, delay } from 'rxjs/operators';

@Injectable()
export class MyEffects {
  loadData$ = createEffect(() => this.actions$.pipe(
    ofType(MyActions.loadData),
    delay(1000),
    map(() => MyActions.loadDataSuccess({ data: [10, 20, 30] }))
  ));

  constructor(private actions$: Actions) {}
}
A{ data: [], loading: false } immediately after dispatch
B{ data: [], loading: true } immediately after dispatch
C{ data: [10, 20, 30], loading: true } immediately after dispatch
D{ data: [10, 20, 30], loading: false } after 1 second delay
Attempts:
2 left
💡 Hint

Consider the timing of the effect and reducer updates.

🧠 Conceptual
expert
2:00remaining
Why use effects instead of components for side effects?

In Angular with NgRx, why is it better to handle side effects like HTTP calls inside effects rather than inside components?

AEffects centralize side effects, keep components simple, and allow better testing and state management.
BComponents cannot perform HTTP calls directly, so effects are required.
CEffects run on the server only, improving performance.
DUsing effects avoids the need for reducers in state management.
Attempts:
2 left
💡 Hint

Think about separation of concerns and testability.

Practice

(1/5)
1. What is the main purpose of Effects in Angular applications?
easy
A. To define routes in the application
B. To style components dynamically
C. To handle side tasks like data fetching or logging outside components
D. To manage component templates

Solution

  1. 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.
  2. Step 2: Compare with other options

    Styling, template management, and routing are handled by other Angular features, not Effects.
  3. Final Answer:

    To handle side tasks like data fetching or logging outside components -> Option C
  4. Quick 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
A. const loadData$ = createEffect(() => { this.actions$.pipe(ofType(load), switchMap(() => fetchData())); });
B. const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), switchMap(() => fetchData())));
C. const loadData$ = createEffect(this.actions$.pipe(ofType(load), switchMap(() => fetchData())));
D. const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), map(() => fetchData())));

Solution

  1. Step 1: Check the syntax of createEffect

    The createEffect function expects a function returning an observable, so it should be () => this.actions$.pipe(...).
  2. Step 2: Verify operators used

    Using switchMap is correct for side effects that return new observables. const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), switchMap(() => fetchData()))); uses this correctly.
  3. Final Answer:

    const loadData$ = createEffect(() => this.actions$.pipe(ofType(load), switchMap(() => fetchData()))); -> Option B
  4. Quick 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:
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
A. The API call is ignored and no action is dispatched
B. The effect causes a syntax error and stops
C. Only loadDataFailure action is dispatched immediately
D. The API call is made, and on success, loadDataSuccess action is dispatched

Solution

  1. Step 1: Understand the effect flow

    When loadData action is dispatched, the effect listens and triggers the API call via switchMap.
  2. Step 2: Analyze success and error handling

    On success, map dispatches loadDataSuccess with data; on error, catchError dispatches loadDataFailure.
  3. Final Answer:

    The API call is made, and on success, loadDataSuccess action is dispatched -> Option D
  4. Quick 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
A. The catchError operator should return an observable
B. The switchMap should not use action parameter
C. The map operator must return the original action
D. The effect should not use createEffect function

Solution

  1. Step 1: Check catchError usage

    The catchError operator must return an observable, but here it returns an action object directly.
  2. Step 2: Correct catchError return

    Wrapping the action in of() makes it an observable, fixing the error.
  3. Final Answer:

    The catchError operator should return an observable -> Option A
  4. Quick 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
A. Use two separate effects: one for API call with dispatch, another for logging with dispatch: false
B. Use one effect with switchMap for API call and tap for logging inside the same pipe
C. Use one effect with map for API call and catchError for logging
D. Use one effect with filter to block logging and API call

Solution

  1. 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 with dispatch: false.
  2. Step 2: API call effect dispatches success or failure

    The main effect handles the API call and dispatches loginSuccess or loginFailure accordingly.
  3. Step 3: Final design

    Two effects keep code clean and responsibilities clear: one for API calls with dispatch, one for logging without dispatch.
  4. Final Answer:

    Use two separate effects: one for API call with dispatch, another for logging with dispatch: false -> Option A
  5. Quick 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