Angular 6+ TypeError:无法读取未定义的属性“ firstName”

时间:2018-08-18 00:41:42

标签: angular typescript observable

我的(Angular 6.1.2)视图在我的可观察对象之前加载,因此创建了未定义的错误。控制台错误后,数据正​​确地存储在那里。

组件

ngOnInit() {
   this.route.params.subscribe(params => {
        this.UserId = params['id'];

        this.objectService.get(this.UserId).subscribe((ret: user) => {
            this.User = user;
        });
    });
}

服务

public get(id: string): Observable<User> {
    return this.http.get<User>(`${this.api}/${id}`);
}

HTML

<h1>{{User.firstName}}</h1>

首先检查它可以消除错误。

<h1 *ngIf="User">{{User.firstName}}</h1>

但是我想从控制器和/或服务中知道如何正确执行此操作,这样我的视图就可以工作而无需检查数据。 使用内存中的API btw。

UPDATE 2019: 我已经切换到使用路由器解析数据,然后可以通过模板中的异步管道轻松解决此问题。这种方法使我省去了很多麻烦。

更新: 看来我们不应该在视图中进行检查。最好在使用变量之前正确设置它们。像这样设置变量时,我选择利用导出的类:

public user: User = new User();将停止未定义的错误。

5 个答案:

答案 0 :(得分:2)

您可以通过三种方式解决此问题:

1-与?之类的<h1>{{User?.firstName}}</h1>绑定变量之前先进行检查

2-以empt对象User = {}开头的变量;

3-使用empt用户实例启动变量

class User {
  name: string;
  ...
}

class UserGrid {
  user: User = new User();
}

错误显示cannot read property of undefined

提示:变量名不要使用首字母大写。这适用于user: User = new User();

之类的类和类型

答案 1 :(得分:2)

您是对的,理想情况下,我们不应该在视图中放入检查逻辑。您可以执行以下操作:

在您的组件中:

public firstName: string;

ngOnInit() {
    this.route.params.subscribe(params => {
        this.UserId = params['id'];

        this.objectService.get(this.UserId).subscribe((ret: user) => {
            if (user) {
                this.firstName = user.firstName;
            }
        });
    });
}

然后在您的视图中html:

<h1>{{firstName}}</h1>

此外,作为订阅和更好性能的最佳实践,您应该订阅ngOnInit,然后取消订阅ngOnDestroy,如下所示:

import { Subscription } from "rxjs";

public firstName: string;

private userSub: Subscription;

ngOnInit() {
    this.route.params.subscribe(params => {
        this.UserId = params['id'];

        this.userSub = this.objectService.get(this.UserId).subscribe((ret: user) => {
            if (user) {
                this.firstName = user.firstName;
            }
        });
    });
}

public ngOnDestroy() {
    this.userSub.unsubscribe();
}

答案 2 :(得分:1)

首先,您现在的方法是正确的方法之一。另一个更好的方法是@vinagreti建议的解决方案1。

之所以发生这种情况,是因为在初始化组件时,模板已加载,但是CompletionItem对象是User,因为undefined位于异步rxjs调用内。

这就是在模板this.User = user;中返回错误的原因,因为您正在从未定义中读取{{User.firstName}}

@vinagreti提出的解决方案已经是最好的解决方案。就我个人而言,在大多数情况下,我更喜欢使用firstName

答案 3 :(得分:1)

Rxjs switchmap是在另一个订阅中进行订阅的优雅方式

User={}
ngOnInit() {
   this.route.params.switchMap(params=>{
     this.objectService.get(params['id'])
   }).subscribe((ret: user) => {
            this.User = ret;
        });
    });
}

答案 4 :(得分:0)

一种处理方法是用空的firstName初始化组件中的User