Best practices for initializing model objects in a Redux or NgRx application architecture

Context:

The development team is currently working on a sophisticated REST-based web application using Angular and the @ngrx library for managing state effectively.

In order to represent entities retrieved from the server, such as accounts and users, we have decided to create TypeScript classes. This approach offers benefits like reducing dependency on API changes and encapsulating key functionalities like creating a `fullName` property by concatenating first and last names.

One challenge we are facing is determining the optimal timing for initializing these model entities within our application. Should we instantiate them early on, when fetching data in a service, or postpone it until they are used in specific components?

this.apiService.fetch(AccountService.URL)
      .map(accounts => accounts.map((a: AccountResponse) => new Account(a)));

Although the current method of initializing and storing Account objects works, adhering to ngrx/redux best practices raises concerns about maintaining only plain objects in the store for serialization purposes.

Following this advice would require delaying the initialization of Account objects until much later in the application flow, potentially at the component level rather than during data retrieval.

This approach seems counterintuitive as it involves passing raw account response objects throughout the application, diminishing the purpose of encapsulating them within model objects.

Comparing our structure with the simplicity of the @ngrx/example book app, which does not utilize model objects for server responses, adds another layer of complexity to our decision-making process.


Inquiries:

  • Aside from serialization challenges, what drawbacks might arise from storing initialized classes in the state?

  • If plain objects are preferred in the store, where do you recommend initializing model classes within the data flow of the application?

Answer №1

When working with ngrx, it's helpful to think of it as more than just a shared object cache in JavaScript; consider it like a database. Just as you wouldn't store JavaScript helpers in a database, the same principle applies to ngrx.

To optimize your approach, you can choose to replace model functions with utility methods or wrap selector results using an observable operator. For example, use

state.pipe(select(mySelector), myWrapFunction)
, although this may result in recreating the wrapper each time.

Exploring the viewmodel design pattern, such as [MVVM] (), can provide insights into similar approaches that align with your goals.

Answer №2

If you're interested, take a look at this sample demonstrating how to set up the initial state of a feature in the ngrx store. I trust this is exactly what you need.

Answer №3

Hey @kyranjamie, I've been exploring the best way to handle this situation. Let me make sure I understand your approach correctly. You store a plain object in a state and when a component requires that object, it utilizes a service like HomeService to retrieve a HomeModel object instead of just a plain object.

@Injectable({
  providedIn: 'root'
})
export class HomeService {

  constructor() {
  }

  public getSelectedHome(homeObject: HomeJSON) {
    return Object.assign(new HomeModel(), homeObject);
  }
}

The component then subscribes to the state changes, rather than directly accessing the plain object from the state. It employs the HomeService to convert the plain object into a class object (HomeModel).

ngOnInit() {
    this.store.pipe(select(getSelectedHome)).subscribe(
      home => {
        this.home = this.homeService.getSelectedHome(home);
      }
    );
  }

Am I grasping your method correctly?

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

How to efficiently eliminate duplicates from a JSON array using Angular2

Struggling with filtering my JSON array in Angular2 after transitioning from Angular 1.x. It used to be so simple using 'unique' in the filter function to remove duplicates. Here is a snippet of the JSON data: {"app":"database_1", "host":"my_h ...

Encountered an NPM installation error: JSON input unexpectedly ended while parsing near '...nt-webpack-plugin":"0'

While setting up a fresh Angular 5 project: node version: 8.9.2 npm version: 5.5.1 Here is the command I used: npm install -g @angular/cli This is the error I encountered: npm ERR! **Unexpected end of JSON input while parsing near '...nt-webpack-p ...

Tips for testing the window.innerWidth property in Angular 8?

I am relatively new to Angular and TDD. Right now, I am attempting to test a function that is called during a resize event. Below is the code snippet in question: header.component.ts @Component({ selector: 'app-header', templateUrl: &ap ...

Leveraging Angular2 router functionality on the Heroku platform

My Angular2 application is successfully deployed on Heroku and functions properly with the "www.example.com" format. However, when I try to access a specific page by typing "www.example.com/page" into the search bar, it returns an error saying "cannot G ...

Utilizing string to access property

Is there a better way to access interface/class properties using strings? Consider the following interface: interface Type { nestedProperty: { a: number b: number } } I want to set nested properties using array iteration: let myType: Type = ...

Unable to implement client-side functionalities in Angular 17 with server-side rendering

view image description hereview image description here Is there a way to make my component run on the client side, similar to "use client" in Next.js? This is my first time working with server-side rendering in Angular, and everything works fine when it&a ...

What is the reason for deprecating the practice of utilizing data and errors in the subscribe/observable method in Angular?

What is the reason for this code being deprecated? And what is the proper format? fetchPeople() { this.peopleService.fetchPeopleList().subscribe( (data) => { console.log(data); }, (error) => { console.log(error); } ); } ...

What is the process for applying this specific style to a certain element?

Here is an example of an element in an Angular2 app: <div class="ticket-card" [ngStyle]="{'background': 'url(' + ticketPath + ')' , 'background-size': 'cover'}"> I would like to enhance the style b ...

Issues arise when attempting to assign GraphQL types, generics, and NestJS Type<> as they are not interchangeable with Type<&

I've been attempting to use this definition: import { GraphQLScalarType } from 'graphql'; import { Type } from '@nestjs/common'; export function createFilterClass<T extends typeof GraphQLScalarType>( FilterType: Type&l ...

Angular 5 - Strategies for excluding specific properties from Observable updates

Currently, I am in the process of developing a webpage where users can view and like various videos. The video content and user likes are stored in a database, and I have implemented two Angular services for handling data retrieval and storage. However, I ...

Messages from the websocket, rxjs, and .net are currently not coming through to me

Currently, I am attempting to implement a straightforward WebSocket solution where an integer is sent to the socket from a dotnet application and then retrieved in my rxjs. The sending process is simple and error-free. Assuming that values are being succe ...

minimize the size of the image within a popup window

I encountered an issue with the react-popup component I am using. When I add an image to the popup, it stretches to full width and length. How can I resize the image? export default () => ( <Popup trigger={<Button className="button" ...

Discover the power and ease of combining Angular with OIDC Implicit Flow for seamless

I have integrated the angular-auth-oidc-client package for authentication in my Angular application with our OIDC server. While using the implicit flow, some users face log out issues when the access token expires. To address this, I decided to implement t ...

"Struggling with setting the default checked state for single and multiple checkboxes? The ng-init method with checkboxModel.value=true seems to be ineffective – any suggestions

<input type="checkbox" ng-model="isChecked.value" ng-true-value="'yes'" ng-false-value="'no'" ng-click='handleCheckboxChange(isChecked.value, idx);' ng-init="isChecked.value=true" /> ...

Tips for Integrating an Angular App into a Different Website

I have an Angular application hosted at www.A.com, My client has a website hosted at www.B.com I am looking to enable my client to embed the Angular app on their webpage without physically copying the application files. I want them to simply add some HTML ...

What is the best way to create a React text box that exclusively accepts numeric values or remains empty, and automatically displays the number keypad on mobile devices?

While there are numerous similar questions on StackOverflow, none of them fully address all of my requirements in a single solution. Any assistance would be greatly appreciated. The Issue at Hand Within my React application, I am in need of a text box tha ...

In React, the Textarea component that displays the character count only updates its value after a page reload

Contained within this element is the following component: import React, { useEffect, useState } from 'react'; import { TextareaTestIds } from '../utils/test-ids'; export interface TexareaProps extends React.TextareaHTMLAttributes<H ...

Implementing a searchable drop-down in AngularWould you like to learn how

I'm struggling with adding search functionality to my dynamic dropdown. If anyone could assist me in implementing the search feature, I would greatly appreciate it. I have successfully created a dropdown with search for static data but am facing chall ...

NgZone is no longer functioning properly

Seemingly out of the blue, my NgZone functionality has ceased to work. I'm currently in the process of developing an application using Ionic, Angular, and Firebase. An error is being thrown: Unhandled Promise rejection: Missing Command Error ; Zon ...

When implementing a sizable Angular material popover, ensure that the parent content is designed to allow scrolling

I have a custom popover feature in my current project, which includes checkboxes beneath the main content. Everything is functioning properly at the moment, but I've encountered an issue when the screen's resolution is reduced - the content at th ...