You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中ngAfterViewInit无法读取ngOnInit赋值的login_info变量

Hey, let's break down why you're hitting that Cannot read property 'nickname' of undefined error and walk through how to fix it.

The Root Cause

The problem boils down to timing between Angular lifecycle hooks and asynchronous data:

  1. ngOnInit runs first, but your call to auth.getUser$() is an asynchronous Observable. The callback inside subscribe() doesn’t execute immediately—it waits until the auth service actually returns user data.
  2. Angular moves on to run ngAfterViewInit before that subscription callback fires. At this point, this.login_info is still undefined, so trying to access this.login_info.nickname throws the error.
  3. Hardcoding 'myname' works because it doesn’t depend on that asynchronous variable—you’re passing a valid string directly.

Fix 1: Move Paginator Logic to the User Data Callback (Simplest Solution)

The most straightforward fix is to set up the paginator’s page subscription after you’ve received and assigned the user data. This guarantees this.login_info is defined when you use it.

Modify your component code like this:

ngOnInit() {
  this.dataSource2 = new DataPaginatedService(this.pastSprintService);
  this.auth.getUser$().subscribe(val => {
    this.login_info = val;
    console.log('hummm-val-log', val.nickname);
    this.loadData();
    
    // Initial data load
    this.dataSource2.loadUserSprint(
      this.login_info.nickname,
      '',
      'asc',
      0,
      2
    );
    this.dataSource2.totalCountItem.subscribe(total => {
      this.totalCount = total;
    });

    // Set up paginator subscription NOW that login_info exists
    this.paginator.page
      .pipe(
        tap(() => {
          this.dataSource2.loadUserSprint(
            this.login_info.nickname, // Safe to use now
            '',
            'asc',
            this.paginator.pageIndex,
            this.paginator.pageSize
          );
          this.dataSource2.totalCountItem.subscribe(total => {
            this.totalCount = total;
          });
        })
      )
      .subscribe();
  });
}

// Clear out the old ngAfterViewInit logic
ngAfterViewInit() {
  // No paginator code here anymore
}

Fix 2: Add Guard Clauses (Quick Safety Net)

If you prefer keeping paginator logic in ngAfterViewInit, you can add checks to ensure this.login_info exists before accessing its properties:

ngAfterViewInit() {
  this.paginator.page
    .pipe(
      startWith(null),
      tap(() => {
        // Skip execution if login_info isn't ready yet
        if (!this.login_info) return;
        
        this.dataSource2.loadUserSprint(
          this.login_info.nickname,
          '',
          'asc',
          this.paginator.pageIndex,
          this.paginator.pageSize
        );
        this.dataSource2.totalCountItem.subscribe(total => {
          this.totalCount = total;
        });
      })
    )
    .subscribe();
}

Note: This is a safety net, not a full fix—your first paginator trigger might still run before login_info loads, leading to empty initial data. Fix 1 is better for consistency.

Fix 3: Use a BehaviorSubject (Robust, Scalable Approach)

For a more maintainable solution, store the user data in a BehaviorSubject so you can react to it anywhere in the component:

// Add this to your component class
import { BehaviorSubject, combineLatest } from 'rxjs';
import { filter } from 'rxjs/operators';

private loginInfo$ = new BehaviorSubject<any>(null);

ngOnInit() {
  this.dataSource2 = new DataPaginatedService(this.pastSprintService);
  this.auth.getUser$().subscribe(val => {
    this.login_info = val;
    this.loginInfo$.next(val); // Emit user data to the subject
    console.log('hummm-val-log', val.nickname);
    this.loadData();
    
    this.dataSource2.loadUserSprint(
      this.login_info.nickname,
      '',
      'asc',
      0,
      2
    );
    this.dataSource2.totalCountItem.subscribe(total => {
      this.totalCount = total;
    });
  });
}

ngAfterViewInit() {
  // Combine paginator events with login state
  combineLatest([this.paginator.page, this.loginInfo$])
    .pipe(
      startWith([null, null]),
      filter(([_, loginInfo]) => !!loginInfo), // Only proceed if user data exists
      tap(([pageEvent, loginInfo]) => {
        const pageIndex = pageEvent?.pageIndex || 0;
        const pageSize = pageEvent?.pageSize || 2;
        
        this.dataSource2.loadUserSprint(
          loginInfo.nickname,
          '',
          'asc',
          pageIndex,
          pageSize
        );
        this.dataSource2.totalCountItem.subscribe(total => {
          this.totalCount = total;
        });
      })
    )
    .subscribe();
}

This ensures paginator events only trigger once user data is available, eliminating race conditions entirely.

内容的提问来源于stack exchange,提问作者baronming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:44:54