Задача
Отрефакторить код компонента. Найдите проблемы и исправьте их.
@Component({
selector: "user",
template: "<div>{{user.name}}</div>",
})
export class UserComponent {
@Input() userId: string;
public user: UserInterface;
constructor() {
const userSerive = new userService();
userSerive.getUser(this.userId).subscribe((user) => (this.user = user));
}
}Проблемы
Что не так с этим кодом
- Сервис создаётся через
newвместо инъекции — ломается DI, тестируемость, синглтон-поведение.- Обращение к
@Input() userIdв конструкторе — на этот момент input ещё не установлен (undefined). Данные приходят только кngOnInit.- Подписка без отписки — утечка памяти при уничтожении компонента.
- Шаблон
{{user.name}}упадёт, покаuserне загрузился (нет?.или*ngIf).- Опечатка в имени переменной (
userSerive) и класс сервиса с маленькой буквы (userService).
Решение
Оптимальное решение (async pipe, без ручных подписок)
@Component({ selector: "user", template: "<div *ngIf=\"user$ | async as user\">{{ user.name }}</div>", }) export class UserComponent implements OnInit { @Input() userId: string; user$: Observable<UserInterface>; constructor(private userService: UserService) {} ngOnInit(): void { this.user$ = this.userService.getUser(this.userId); } }
asyncpipe сам подписывается и отписывается — утечки нет, шаблон безопасен через*ngIf.
Вариант с ручной подпиской и takeUntilDestroyed
@Component({ selector: "user", template: "<div>{{ user?.name }}</div>", }) export class UserComponent implements OnInit { @Input() userId: string; user: UserInterface; private destroyRef = inject(DestroyRef); constructor(private userService: UserService) {} ngOnInit(): void { this.userService .getUser(this.userId) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => (this.user = user)); } }