Как избежать боли Observable при обмене данными между маршрутами в Angular?
Когда мы стремимся обмениваться данными между маршрутами, кажется, что единственным жизнеспособным решением является использование сервиса. Поскольку мы хотим, чтобы данные обновлялись в представлении при их обновлении, мы должны использовать BehaviorSubject
,
Итак, поправьте меня, если я ошибаюсь, но простой компонент будет выглядеть так:
@Component({
selector: 'user-info',
template: `
{{($user | async).firstName}}
<button (click)="updateName()"></button>
`
})
export class UserInfoComponent {
private $user;
private subscribe;
constructor(private service: UserService) {
this.user$ = this.service.get();
}
updateName() {
this.subscribe = this.service.get().subscribe(user =>
this.service.update({...user, firstName: 'new-name'})
);
}
ngOnDestroy() {
this.subscribe.unsubscribe();
}
}
Это звучит очень печально, потому что если бы мы не использовали маршрутизатор, мы могли бы просто вызвать компонент с <user-info [user]="user | async"></user-info>
и было бы намного чище
@Component({
selector: 'user-info',
template: `
{{user.lastName}}
<button (click)="updateName()"></button>
`
})
export class UserInfo2Component {
@Input() user: User;
constructor(private service: UserService) {}
updateName() {
this.service.update({...user, lastName: 'new-name'});
}
}
Поэтому мой вопрос: почему так сложно обмениваться данными между маршрутами? Есть ли лучшее решение, которое я мог бы пропустить?
2 ответа
Ты можешь использовать ngrx
избегать использования наблюдаемых. Это основано на redux
концепция.
Таким образом, вы настраиваете данные в хранилище, передаете некоторый идентификатор в свой маршрут и используете этот идентификатор в следующем маршруте, чтобы получить данные из хранилища. Теперь, поскольку хранилище является единственным источником данных здесь, вам не нужно постоянно передавать данные между маршрутами, каждый маршрут может устанавливать данные для хранилища, а другие маршруты могут получать к нему доступ из хранилища.
Подробнее об этом читайте здесь: Зачем использовать NGRX вместо сервисов с внедрением в конструктор и с наблюдаемыми?
Ваша ошибка заключается в обработке логики обновления в компонентах, а не в сервисе.
Попробуйте что-то вроде этого:
user.service
import { Component, Input } from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
export class UserService {
private user = new BehaviorSubject({
firstName: 'Tomasz'
})
user$ = this.user.asObservable();
update(user: any) {
this.user.next({
...this.user.getValue(),
...user
})
}
}
app.component.ts
import { Component } from '@angular/core';
import {UserService} from './user.service';
@Component({
selector: 'my-app',
template: `
<input (keydown.enter)="updateUser(input.value); input.value=''" #input>
{{ user$ | async | json }}
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
user$;
constructor(private userService: UserService) {
this.user$ = this.userService.user$;
}
updateUser(firstName: string) {
this.userService.update({ firstName });
}
}