Как избежать боли 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 });
  }
}

Живая демо

Другие вопросы по тегам