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:
ngOnInitruns first, but your call toauth.getUser$()is an asynchronous Observable. The callback insidesubscribe()doesn’t execute immediately—it waits until the auth service actually returns user data.- Angular moves on to run
ngAfterViewInitbefore that subscription callback fires. At this point,this.login_infois stillundefined, so trying to accessthis.login_info.nicknamethrows the error. - 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

