Performance: Effect for side effects
This affects how and when side effects run in Angular components, impacting interaction responsiveness and rendering stability.
Jump into concepts and practice - no test required
import { Component, effect, signal } from '@angular/core'; @Component({ selector: 'app-example', template: `<p>{{count()}}</p>` }) export class ExampleComponent { count = signal(0); constructor() { effect(() => { const current = this.count(); document.body.style.backgroundColor = current % 2 === 0 ? 'lightblue' : 'lightgreen'; }); setInterval(() => this.count.update(c => c + 1), 1000); } }
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-example', template: `<p>{{count}}</p>` }) export class ExampleComponent implements OnInit { count = 0; ngOnInit() { setInterval(() => { this.count++; // Direct DOM manipulation or heavy logic here document.body.style.backgroundColor = this.count % 2 === 0 ? 'lightblue' : 'lightgreen'; }, 1000); } }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Direct DOM manipulation in ngOnInit | Multiple direct writes | Multiple reflows per interval | High paint cost due to style thrashing | [X] Bad |
| Angular effect with signals | Reactive updates only | Single reflow per update | Lower paint cost with batched updates | [OK] Good |
Effect in Angular?pipe with operators like ofType to filter actions and tap for side effects.pipe, ofType, and tap. Others misuse operators or subscribe directly, which is incorrect inside Effects.loadData$ = createEffect(() => this.actions$.pipe(
ofType('LOAD_DATA'),
tap(() => console.log('Data loading started'))
), { dispatch: false });dispatch: false means this Effect does not send out new actions after running.tap operator runs side code like logging but does not change or dispatch actions.saveData$ = createEffect(() => this.actions$.pipe(
ofType('SAVE_DATA'),
map(() => this.api.save()),
tap(() => console.log('Save triggered'))
));this.api.save() likely returns a Promise or void, not an action.dispatch: false is set, which is missing here.switchMap allows calling the async login API and switching to its result stream.map creates a success action, and catchError returns a failure action wrapped in of to keep the stream alive.