Noé Rivera
Noé Rivera

Reputation: 33

Console.log returning undefined on ngOninit, but returning data on function

I have this problem, i want to print whatever the data is in userdata variable. but I only get an undefined text when making a console.log().

but when I place this console log inside a function and call it with a button it throws the actual data. I tried to put the console.log inside a function and call it at the end of ngoinint but this does not work.

my code

public userData!: any;
    
ngOnInit(): void {
    this.getUserData(this.userId);
    console.log(this.userData) //this prints undefined
    
}

getUserData(id: number) {
    this.userService.getUserData(id).subscribe((response) => {
        this.userData = response.data;
        this.userCategory = response.data.UsersCategory;
    });
}

this.printData(){
    // this only works if i press a button to call it 
    // but does not work if I call this function inside ngOnInit
    console.log(this.userData);
}

Upvotes: 1

Views: 1655

Answers (1)

Jonathan Stellwag
Jonathan Stellwag

Reputation: 4267

Your described goal

i want to print whatever the data is in userdata variable.

The moment you log userData is at the ngOnInit. At this time (lifecycle hook) the value has not been set yet.

What could cause userData to be set?

userData is only set at only place in your code - inside the subscription that is within the getUserData function.

Requirements to receive a value

  1. getUserData has to be called. That will create a subscription
  2. this.userService.getUserData(id) has to emit at least one value

Your code does neither show a getUserData call nor a observable emit this.userService.getUserData(id) is shown.

Misconcept

Your code looks a lot like synchronuous imperative. Although RxJS is reactive and handles asynchronuous values for you. I think you have a missunderstanding of how RxJS is intended to be used. Some tips that might help

  1. Try to subscribe as early as possible to observables
ngOnInit() {
   observable$.subscribe(value => userData = value)
}
  1. If your observables dont cover all informations and events > create one with that fits your needs
private readonly getUserData$$ = new Subject()

getUserData(id: number) {
    this.getUserData$$.next(id)
}
  1. Use the power of rxjs operators to create a pipe that fits your needs
private readonly getUserData$$ = new Subject()

public userData: any;

ngOnInit() {
    getUserData$$.pipe(
        switchMap(id => this.userService.getUserData(id)
    ).subscribe(response => this.userData = response.data)
}

getUserData(id: number) {
    this.getUserData$$.next(id)
}

Upvotes: 1

Related Questions