Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize the initial state object to be an empty object instead of undefined

I want the cars object in the customer class to be empty instead of undefined as I have selectors to select the cars object and I want it to return empty rather than undefined.

Here is my initial state.

export const initialState: CustomerState = {
  customer: new Customer(),
};

export class Customer{
id: number;
age: number;
cars: carClass;
phoneNumbers: string[];
}

export class carClass{
name:string;
citiesRegistered:city[];
}

export class city{
parks: string[],
lakes: string[],
schools: string[]
}

Here is my reducer with selector.

const getCustomerState= createFeatureSelector<CustomerState>('customer');

export const getCustomerCarsCities = createSelector(
  getCustomerState,
  state => state.customer.cars.citiesRegistered   // There is an error here
);

Here is the component to get cities registered

  getCustomerCitiesRegistered$: Observable<any>;

  constructor(private store: Store) {
    this.getCustomerCitiesRegistered$ = this.store.select(getCustomerCarsCities );
  }

Here is the html

<div *ngIf="getCustomerCitiesRegistered$ | async as cities">   // This is undefined
   
    <div class="parks">
      <app-parks [parkOptions]="cities.parks">
      </parks>
    </div>
</div>

I get an error that cities is undefined. How can I get an empty object if the state is empty

like image 463
Learn AspNet Avatar asked Nov 25 '25 19:11

Learn AspNet


1 Answers

You have at least three options:

Option 1:

You can initialize the necessary fields in your classes:

export class Customer {
  id: number;
  age: number;
  cars = new CarClass(); // Since you access this it needs to be initialized.
  phoneNumbers: string[] = []; // It is good practice to use empty arrays over null | undefined.
}

export class CarClass {
  name:string;
  citiesRegistered: City[] = []; // Since you access this it needs to be initialized.
}

export class City {
  parks: string[] = [],
  lakes: string[] = [],
  schools: string[] = []
}

Option 2

You can initialize the customer with the necessary fields in a factory method:

const createEmptyCustomer = () => {
    const customer = new Customer();
    customer.cars = new CarClass();
    customer.cars.citiesRegistered = [];

    // maybe init more fields...

    return customer;
};

export const initialState: CustomerState = {
  customer: createEmptyCustomer()
};

Option 3

Let your selector state return a valid value:

export const getCustomerCarsCities = createSelector(
  getCustomerState,
  state => state.customer?.cars?.citiesRegistered || []
);

This last option is not advised if you are planning to modify the array, because it will not reflect back to the customer.

Now you have a second problem

You are referencing cities.parks:

<div class="parks">
  <app-parks [parkOptions]="cities.parks"></app-parks>
</div>

This is not going to work, because you are essentially writing [].parks. Maybe you meant to write a loop or something:

<div class="parks">
  <ng-container *ngFor="let city of cities">
    <app-parks [parkOptions]="city.parks"></app-parks>
  </ng-container>
</div>
like image 80
Silvermind Avatar answered Nov 27 '25 11:11

Silvermind



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!