How to Use distinctUntilChanged in RxJS for Angular
Use the
distinctUntilChanged operator in RxJS to ignore consecutive duplicate values emitted by an observable. It helps prevent unnecessary updates by only passing values that differ from the previous one.Syntax
The distinctUntilChanged operator is used as a pipeable operator in RxJS. It can be used with or without a comparison function.
distinctUntilChanged(): Uses strict equality (===) to compare values.distinctUntilChanged(compareFunction): Uses a custom function to compare previous and current values.
typescript
import { distinctUntilChanged } from 'rxjs/operators'; observable.pipe( distinctUntilChanged(), // or with a custom compare function distinctUntilChanged((prev, curr) => prev.id === curr.id) )
Example
This example shows an observable emitting numbers with some duplicates. Using distinctUntilChanged filters out consecutive repeated numbers, so only changes are logged.
typescript
import { of } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; const numbers$ = of(1, 1, 2, 2, 2, 3, 1, 1); numbers$ .pipe(distinctUntilChanged()) .subscribe(value => console.log(value));
Output
1
2
3
1
Common Pitfalls
One common mistake is expecting distinctUntilChanged to filter out all duplicates, but it only removes consecutive duplicates. Non-consecutive duplicates will still pass through.
Another pitfall is not providing a proper comparison function when working with objects, which leads to unexpected behavior because objects are compared by reference.
typescript
import { of } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; const objs$ = of( { id: 1 }, { id: 1 }, { id: 2 }, { id: 2 }, { id: 1 } ); // Wrong: no custom compare, compares object references objs$ .pipe(distinctUntilChanged()) .subscribe(console.log); // Right: compare by id property objs$ .pipe(distinctUntilChanged((prev, curr) => prev.id === curr.id)) .subscribe(console.log);
Output
{ id: 1 }
{ id: 1 }
{ id: 2 }
{ id: 2 }
{ id: 1 }
{ id: 1 }
{ id: 2 }
{ id: 1 }
Quick Reference
- distinctUntilChanged(): Filters out consecutive duplicate primitive values.
- distinctUntilChanged(compareFn): Use for custom comparison, especially with objects.
- Only consecutive duplicates are filtered, non-consecutive duplicates pass through.
- Useful to reduce unnecessary UI updates or network calls.
Key Takeaways
distinctUntilChanged filters out only consecutive duplicate values from an observable.
Use a custom compare function with distinctUntilChanged when working with objects.
It helps optimize performance by preventing unnecessary repeated emissions.
Without a compare function, it uses strict equality (===) for comparison.
Non-consecutive duplicates are not filtered by distinctUntilChanged.