Navigating between two components eliminates the need for ongoing subscriptions within the NGRX store

In my application, I have two main pages named Dashboard and Transactions, along with a component called Sidebar responsible for navigation control.

The initial transition from the Dashboard to the Transactions page involves subscribing to the user state in the store. This process functions correctly, allowing me to retrieve the userID and pass it down to child components for use.

export class TransactionsComponent implements OnInit {
  userID;

  constructor(private store: Store<AppState>, private spinner: NgxSpinnerService) {}

  ngOnInit() {
    this.spinner.show();
    this.store.select('user').subscribe(
      user => { if (user) { this.userID = user.uid; } }
    );
  }
}

However, when navigating back to the Dashboard and then returning to the Transactions page, I encounter an issue where the user ID does not resolve, leading to an endless loading spinner.

Furthermore, upon transitioning from the transactions page to the dashboard, the subscription within the Sidebar component is lost.

export class SidebarComponent implements OnInit {
  user$: Observable<User>;

  constructor(public auth: AuthService, private store: Store<AppState>) {}

  ngOnInit(): void {
    this.user$ = this.store.select('user');
    this.store.dispatch(new userActions.GetUser());
  }
}

To address this challenge, here is the effect responsible for retrieving the user ID:

 @Effect()
 getUser: Observable<Action> = this.actions.pipe(
 ofType(userActions.GET_USER),
 map((action: userActions.GetUser) => action.payload ),
 switchMap(payload => this.afAuth.authState),
 delay(2000), // This delay can be removed, used only for loading spinner
 map( authData => {
     if (authData) {
       const user = new User(authData.uid, authData.displayName);
       return new userActions.Authenticated(user);
     } else {
       return new userActions.NotAuthenticated();
     }
 }),
 catchError(err => of(new userActions.AuthError()) )
 );

I anticipate that the Transactions component will retain the user ID state and avoid triggering the loading spinner unnecessarily during subsequent navigations.

Answer №1

The correct code can be found in the SidebarComponent under the usage of user$. It is recommended to create an Observable instead of a subscription.

In the TransactionsComponent, it is advised to follow the same pattern. Is there a specific reason for keeping the user's userID as an independent property?

A more suitable approach would be:

export class TransactionsComponent implements OnInit {
  userId$;

  constructor(private store: Store<AppState>, private spinner: NgxSpinnerService) {}

  ngOnInit() {
    this.userId = this.store.select('user').pipe(
      tap(user => {
        if (user) { // user exists, data has been loaded
          this.spinner.hide();
        } else {
          this.spinner.show(); // no user yet, loading in progress
        }
      }),
      map(user => user ? user.uid : undefined),
      filter(userId => userId !== undefined), // <- optional comment about userId necessity.
    );
  }
}

Then in the template:

<ng-container *ngIf="userId$ | async as userId">
   <child-component [userId]="userId"></child-component>
</ng-container>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to invoke a function only once in typescript?

Struggling to implement TypeScript in React Native for fetching an API on screen load? I've been facing a tough time with it, especially when trying to call the function only once without using timeouts. Here's my current approach, but it's ...

How can Karma unit tests with Jasmine in a TypeScript Node project accurately measure code coverage, even with external dependencies?

We have a unique situation with the code coverage of our project involving a node dependency. It's important to note that the npm dependency source code is actually part of our project, as we are responsible for its development and publication. Here&a ...

Issue detected in the ngx-joyride package: Error found in ./node_modules/ngx-joyride/assets/images/close.svg

During my build process, I encountered an error with ngx-joyride: ERROR in ./node_modules/ngx-joyride/assets/images/close.svg Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type." <line x1="1" y1=" ...

What is preventing me from utilizing a union type in conjunction with redux connect?

Below is a brief example of the code I am working on: import { connect } from "react-redux"; interface ErrorProps { error: true; description: string; } interface NoErrorProps { error: false; } type TestProps = ErrorProps | NoErrorProps; ...

Interactive Angular Interfaces Featuring Numerous Numeric Choices Within the Main Object

I am currently in the process of designing an interface for my Angular project that allows users to search for video games using the WhatToPlay API within RapidAPI. When a user searches for details on a video game, the result will return a game identified ...

Dealing with AOT challenges when integrating ng2-bootstrap into Angular 2 applications

I'm currently developing an Angular 2 app and encountering an error when attempting to create a bundle with AOT compilation following the guidelines in Angular 2 documentation here. The dependency error I'm facing is as follows: Refer to this ...

It seems that in order to use Angular 2 with Firebase Hosting, the hash marking is

Is it possible to set up normal URLs for routes in Angular 2 with Firebase Hosting? An example route would be: I attempted to deploy my website on Firebase hosting with routes structured this way, but I faced issues navigating to the routes. To resolve ...

How can you display data conditionally in Angular 2 using *ngIf?

Below is an example of the show-data component: @Component({ selector: 'show-data', template: `yes! Displaying the show-data directive template!` }) export class ShowData {} And here is its parent component: @Component({ selector: ...

Unable to alter Mui input label color upon focus using theme.ts

In my next.js app, I'm facing an issue with changing the color of the label in a Material UI input field using Mui. Despite updating the theme.ts file to change the border bottom color and label color, only the border bottom color is being applied. T ...

What to do when faced with the Netlify Error "Dependency Installation Failure"?

Having trouble deploying a website created with react and typescript. I keep encountering an error during the initialization phase: https://i.sstatic.net/LNhFJ.png https://i.sstatic.net/w7KTo.png This is all new to me as I just started working with react ...

When using console.log in Angular, it displays an object as [object Object]

After receiving advice, I decided to implement a template driven form. However, when I try to log the userForm.value in the console, all I get is " [object Object] ". Can someone please point out what mistake I might be making? <form *ngIf="data" #us ...

Angular's input event fails to trigger for dynamically generated fields when pasted into them

When working with a form that has dynamically generated input fields, I encountered an issue. I needed to display a preview of the input contents on a div while pasting content into the fields. This project is built using Angular 11. Below is my .ts file: ...

Leveraging the Power of SASS Variables Across Your Entire NativeScript Application

Currently, I am in the process of developing an app using NativeScript 6.4.1 along with Angular 8. In order to enhance my styling capabilities, I have decided to incorporate SASS due to its advantageous features like variable names. My designer has suppli ...

What is the best way to transform this component into a function rather than a class?

import React, { Component } from "react"; class ChatHistory extends Component { render() { const messages = this.props.chatHistory.map((msg, index) => ( <p key={index}>{msg.data}</p> )); return ( <div ...

Why is Django displaying the data I provided as the HttpResponse?

Currently, I am working on a project using Angular 8 and Django. The process involves sending data from an Angular form to Django in order to store it in a database. class NewProfileView(viewsets.ModelViewSet): queryset = NewProfile.objects.all() ...

Combining Angular 2 and Symfony 3 for seamless integration

I am currently working on integrating Angular 2 with Symfony 3. After using npm to install node modules, I encountered an issue linking them from my base view base.html.twig. Despite adding scripts, none of them seem to be working or appearing in the page& ...

Tips on resolving the error message "this.accountService is not defined"

I am new to Angular and JHipster and need help solving a problem. I have not made any changes to the code, it is still using JHipster's default code for login. Stack trace: TypeError: this.accountService is undefined Stack trace: LoginService.protot ...

Display sub-objects within Chart.js

I'm currently tackling a project in Ionic 3 where I am utilizing an API that returns a JSON response with nested objects. My goal is to display certain aspects of these objects within a bar graph using chart.js. Unfortunately, I lack experience in ma ...

Issues Arising from Use of '+' Character in Encoded Token Strings within ASP.NET Core and Angular Application

I'm facing a challenge with handling URL-encoded strings in my ASP.NET 8 Core and Angular 17 application, particularly when dealing with password reset functionality. The issue stems from the presence of the '+' character in the URL-encoded ...

Issue with utilizing Material Button Icon in the header of a datatable in Angular 7

I'm currently facing an issue with incorporating a refresh button into a Material Data Table on Angular 7. Strangely, instead of displaying the icon, refresh, it appears in italicized text. Below is the snippet of code causing the problem: <table ...