What is the best way to share data between Angular components? #204383
Replies: 3 comments
This comment was marked as spam.
This comment was marked as spam.
|
For components that are not in a parent-child relationship, a shared service is the right default, and you only reach for a state management library when the service approach starts to hurt. The part that has changed in recent Angular versions is what you put inside that service: signals cover most cases now, and RxJS stays for the asynchronous work it is actually good at. Shared service with signalsKeep the writable signal private and expose a read-only view plus whatever derived values the components need. Mutations go through methods, so there is a single place where the state changes. @Injectable({ providedIn: 'root' })
export class CartService {
private readonly items = signal<Item[]>([]);
readonly cartItems = this.items.asReadonly();
readonly total = computed(() => this.items().reduce((sum, item) => sum + item.price, 0));
add(item: Item) {
this.items.update(current => [...current, item]);
}
clear() {
this.items.set([]);
}
}Any component injects it with When RxJS is still the better toolUse a subject when the value is a stream rather than a state, or when you need operators. Search boxes, polling, websockets and request cancellation are the typical cases. @Injectable({ providedIn: 'root' })
export class SearchService {
private readonly http = inject(HttpClient);
private readonly query = new BehaviorSubject<string>('');
readonly results$ = this.query.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(q => this.http.get<Result[]>('/api/search', { params: { q } })),
shareReplay({ bufferSize: 1, refCount: true })
);
search(q: string) {
this.query.next(q);
}
}The two approaches mix without friction: When to introduce a state management libraryNgRx or the NgRx SignalStore start to pay off when several unrelated features read and write the same state, when you need an explicit action log and time travel debugging, or when the asynchronous orchestration between effects becomes hard to follow inside plain services. Below that threshold it mostly adds boilerplate: a handful of well scoped services is easier to read and to test. Two practical notesScope matters as much as the mechanism. If the state should be linkable or survive a reload, put it in the URL as route or query parameters and read it back with the router, rather than keeping it only in a service. Filters, pagination and selected tabs belong there. |

Hi!
For unrelated components, a Shared Service is the recommended approach for most apps.
Shared Service with RxJS or Signals: Best for small-to-medium apps. Create a service with a BehaviorSubject (or Angular signal()) and inject it into both components. It's lightweight and easy to maintain.
State Management (NgRx/Elf): Only use this if your app is large, highly complex, and needs global state debugging.
Tip: Start with a Shared Service first!