I am trying to display the initial state of my application on the page.
But when I do a for loop over the state data, I am getting an error Object is possibly 'null'.
Several steps forward: the *ngFor
looks like this now *ngFor="let workout of (workouts | async).workouts"
.
And when I delete .workouts
the error turns to be Type '{ workouts: Workout[]; } | null' is not assignable to type 'NgIterable<any> | null | undefined'
So I assume that my application can't fetch the initial state for some reason. I checked the models, all types of data are correct. I also Googled for this: Type 'object' is not assignable to type 'NgIterable<any> | null | undefined' But it seems like I am doing everything right.
Now the code:
workout.model.ts
import { Exercise } from "./exercise.model"
export interface Workout {
name: string,
exercises: Exercise[]
}
exercise.model.ts
export interface Exercise {
name: string,
completed: boolean
}
actions.ts
import { Action } from "@ngrx/store"
import { Workout } from "../models/workout.model"
export const ADD_WORKOUT = 'ADD_WORKOUT'
export const REMOVE_WORKOUT = 'REMOVE_WORKOUT'
export const UPDATE_WORKOUT = 'UPDATE_WORKOUT'
export class AddWorkout implements Action {
readonly type = ADD_WORKOUT
constructor(public payload: Workout) {}
}
export type Actions = AddWorkout
reducer.ts
import * as WorkoutActions from "../actions/tasks.actions"
const initialState = {
workouts: [{
name: "Day 1",
exercises: [{
name: "push-up",
completed: false
}]
}]
}
export function workoutsReducer(state = initialState, action: WorkoutActions.Actions) {
switch(action.type) {
case WorkoutActions.ADD_WORKOUT:
return {
...state,
workouts: [...state.workouts, action.payload]
};
default:
return state;
}
}
app.module.ts
imports: [
BrowserModule,
StoreModule.forRoot({
workoutsList: workoutsReducer
} as ActionReducerMap<any,any>)
],
workouts-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Workout } from '../models/workout.model';
@Component({
selector: 'app-workouts-list',
templateUrl: './workouts-list.component.html',
styleUrls: ['./workouts-list.component.scss']
})
export class WorkoutsListComponent implements OnInit {
workouts!: Observable<{workouts: Workout[]}>;
constructor(
private store: Store<{workoutsList: {workouts: Workout[]}}>
) { }
ngOnInit(): void {
this.workouts = this.store.select('workoutsList')
}
}
workouts-list.component.html
<div *ngFor="let workout of (workouts | async).workouts">
<div>{{workout.name}}</div>
</div>
I avoid getting the Object is possibly 'null'.
error by using the optional chaining operator.
Try using it after workouts in the for loop.