"Troubleshooting Issue: Angular2 NGRX/Store View Failing to

I apologize for bringing up yet another concern regarding Angular 2 view updates, as I have not been able to find a solution in previous discussions. Although I mention the use of NGRX/Store, I highly doubt that it is the reason why the view is not updating correctly. Strangely enough, it seems to update once (at least), but always remains one step behind. The most recent update never seems to take effect. When the model updates, the previous state reflects in the view. It's quite perplexing indeed. Here is the relevant code:

Relevant Installed packages

    "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "^0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "^3.0.0-rc.1",
    "@angular/upgrade": "2.0.0-rc.5",
    "@ngrx/core": "^1.0.1",
    "@ngrx/store": "^2.0.1",

My main app module

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        RouterModule.forRoot(AppRoutes)
    ],
    declarations: [
        ConsumerApp,
        AppManagement,
        MyApps,
        AppRegistration,
        AppDetails,
    ],
    providers: [
        HTTP_PROVIDERS,
        STORE_PROVIDERS,
        AppManagementService,
    ],
    bootstrap: [
        ConsumerApp
    ]
})
export class AppModule { }

My-Apps Component

@Component({
    selector: 'my-apps',
    template: require('./templates/my-apps.html')
})
export class MyApps implements OnInit, OnDestroy {

    apps = {};
    change = 1;
    userAppsSubscription;

    constructor (
        private appsService: AppManagementService,
        private store: Store<any> ) {}

    ngOnInit () {

        this.userAppsSubscription = this.store
            .select('userApps')
            .subscribe( userApps => {
                this.apps = Object.assign(this.apps, userApps);
                this.change++;
                console.log(this);
            })

        this.appsService.getUserApps();
    }

    ngOnDestroy () {

        this.userAppsSubscription.unsubscribe();
    }
}

My-Apps template

<div id="my-apps">
    <h1>My Apps</h1>
    <h2>{{change}}</h2>
    <p>You currently don't have any registered applications. Click "Register an App" to get started.</p>

    <p [hidden]="!loading">{{apps | json}}</p>

    <div class="apps-container">  
        <div class="col-md-4 col-sm-6" *ngFor="let app of apps.available">
            <button class="block-button">
                <h3>{{app.name}}</h3>
                <p><strong>Description:</strong> {{app.description}}</p>  
            </button>
        </div>
    </div>

</div>

App Management Service

@Injectable()
export class AppManagementService {

    constructor (
        private http: Http, 
        private store: Store<any>) {}

    getUserApps () {

        this.store
            .dispatch({
                type: RETRIEVE_USER_APPS,
                payload: null
            })

        return this.http
            .get(ALL_APPS)
            .toPromise()
            .then(response => {
                this.store
                    .dispatch({
                        type: RECIEVE_USER_APPS,
                        payload: response.json()
                    })
            })
            .catch(response => {
                this.store
                    .dispatch({
                        type: RETRIEVAL_FAILURE_USER_APPS,
                        payload: null
                    })
            });
    }
}

Upon first encountering the "My Apps" page, this is what ends up being displayed.

https://i.sstatic.net/7XwAo.png

However, this is how the view ultimately appears.

https://i.sstatic.net/vbFCs.png

Isn't it bizarre? You can observe that the page was updated with the second state broadcasted by NGRX/Store, but not with the final state which contains the actual content (the list of 6 apps). Why on earth would the view fail to update correctly?

Answer №1

Could you share the code for your reducer?

In my opinion, it would be beneficial to refactor the Init method by avoiding unwrapping the stream. Instead, utilize the async pipe to handle this operation and take care of unsubscribing as well.

You can consider implementing something like the following:

HTML

<div id="my-apps">
    <h1>My Apps</h1>
    <h2>{{change}}</h2>
    <p>There are currently no registered applications. Click "Register an App" to begin.</p>

    <p [hidden]="!loading">{{apps | json}}</p>

    <div class="apps-container">  
        <div class="col-md-4 col-sm-6" *ngFor="let app of ($userAppsSubscription | async).apps.available">
            <button class="block-button">
                <h3>{{app.name}}</h3>
                <p><strong>Description:</strong> {{app.description}}</p>  
            </button>
        </div>
    </div>
</div>

TypeScript

@Component({
    selector: 'my-apps',
    template: require('./templates/my-apps.html')
})
export class MyApps implements OnInit, OnDestroy {

    apps = {};
    change = 1;
    $userAppsSubscription:Observable<string>;

    constructor (
        private appsService: AppManagementService,
        private store: Store<any> ) {}

    ngOnInit () {

        this.userAppsSubscription = this.store
            .select('userApps');

        this.appsService.getUserApps();
    }

    ngOnDestroy () {

        this.userAppsSubscription.unsubscribe();
    }
}

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

Utilizing Leaflet-geotiff in an Angular 6 Environment

I'm currently facing an issue where I am unable to display any .tif image on my map using the leaflet-geotiff plugin. I downloaded a file from gis-lab.info (you can download it from this link) and attempted to add it to my map, but I keep encountering ...

Saving the link to the search results for future reference

Procedure: onSearch(searchString) { if (this.props.history) { this.props.history.push( "/details?search=" + encodeURIComponent(searchString) ); } } Explore Bar: <Search onKeyPress={(event) => ...

Struggling to make the paste event function in Typescript

Here is a snippet of my Typescript code: const pasteFn = (e: ClipboardEvent) => { const { clipboardData } = e; const text = clipboardData?.getData('text/plain'); console.log(text); }; window.addEventListener('paste', pas ...

Having trouble importing one of my node modules, even though the others are working fine

My file structure for Typescript is organized as shown below: src |aws folder | |__s3-controller.ts |events-service folder | |__events-service-request.ts |__index.ts In my index.ts file, I have the following exports defined: export * from './aw ...

Transferring data from a child component to a parent component in Vue without the need for a click

In my Vue project, I have a parent component called ChangeInfo which contains a child component named ShowWorkInfo. The ShowWorkInfo component includes several input forms for updating job information. To manage the data input, I created an object variable ...

Is there a way to customize the default styles of Kendo UI for Angular?

Is it possible to customize the default datepicker styles to look like the design in the second image? https://i.sstatic.net/h8yfA.png https://i.sstatic.net/PfiSf.png ...

Tips for RETRIEVING a particular cookie value in Angular version 14

"I've integrated the ngx-cookie-service library in my Angular project, but I'm experiencing an issue where two different cookies are being retrieved upon login even though the session id is already set in the backend. How can I ensure that m ...

Safari having trouble auto-playing Vimeo iframe embed

Update 6/26/23: Seems like a mysterious change occurred, as now the Vimeo video on project pages is playing automatically for me in Safari without any specific reason. It's working fine on Chrome too. Not sure if Vimeo made an update or if it's r ...

Referring to TypeScript modules

Consider this TypeScript code snippet: module animals { export class Animal { } } module display.animals { export class DisplayAnimal extends animals.Animal { } } The objective here is to create a subclass called DisplayAnimal in the dis ...

No matter which port I try to use, I always receive the error message "listen EADDRINUSE: address already in use :::1000"

Encountered an error: EADDRINUSE - address already in use at port 1000. The issue is within the Server setupListenHandle and listenInCluster functions in the node.js file. I am currently running this on a Mac operating system, specifically Sonoma. Despit ...

How can code snippets be showcased in an HTML page using Angular?

How can I display static code on a webpage using Angular? Is there a method to showcase code snippets in an HTML document? ...

What is the recommended TypeScript type for the NextJS _app.tsx Component and pageProps?

Take a look at the default _app.tsx code snippet from NextJS: function MyApp({ Component, pageProps }) { return ( <Component {...pageProps} /> ) } The issue arises when transitioning to TypeScript, as ES6Lint generates a warning indicating t ...

Angular2: The NgFor directive is designed to work with Iterables like Arrays for data binding

I'm currently working on a university project to develop a web application consisting of a Web API and a Frontend that interacts with the API. The specific focus of this project is a recipe website. Although I have limited experience with technologies ...

Building Angular 2 - Generate Multiple Sections in HTML with the Click of a Button

<div class="schedule-time"> <span>Include Schedule Time <span class="adr" (click)="AddNewSchedule()">+</span></span> ........ </div> <div *ngFor = "let i of OpenNewSchedule"> <div class= ...

What is the best way to set a boolean value for a checkbox in a React project with Typescript?

Currently, I am working on a project involving a to-do list and I am facing an issue with assigning a boolean value to my checkbox. After array mapping my to-dos, the checkbox object displays 'on' when it is unchecked and a 'Synthetic Base E ...

Transmitting Events to JavaScript from Your Custom Module in React Native?

I've been attempting to transfer an event from my module to React Native. I followed the steps outlined here, but it didn't behave as anticipated. I'm not getting any errors, but it simply isn't functioning. Below is my code in Android ...

Tips for clearing an observable in Angular version 4

In the code snippet below, an observable has been created: private permissionSubject = new Subject<any>(); permissionObservable$ = this.permissionSubject.asObservable(); constructor( public apiService: ApiService) { } updatePermissionsDat ...

Adding services to an Angular class instance for dependency injection

When attempting to utilize an instance of a class within a static property of another class, I encountered the following issue: class MyHelper { private authService: AuthService; constructor() { this.authService = inject(AuthService); this ...

Ensuring Type Safety in Typescript

I have a specific requirement where I need to validate the structure of a request body to ensure it conforms to a predefined type. Is there a way or a package that can help achieve this validation? type SampleRequestBody = { id: string; name: string; ...

What steps can I take to turn a decorated service into an injectable component?

I created a decorator factory function that looks like this: export function CustomDecorator (dummyProp: string) { return function<T extends {new (...args: any[]): any}> (ctor: T) { @Injectable() class MyCustomClass extends ...