I have an an array of objects, which is downloaded from the backend, which now I want to to use to populate my state variable. The problem is that the object has multiple levels of nesting.
The state is -
const initialState: SummaryStateInterface = {
summaryList: [], // Problem is only with this one.
editIndex: null,
editItem: null,
addingNew: false,
modifications: false,
isLoading: false,
}
the SummaryStateInterface is this:
export interface SummaryStateInterface {
summaryList: Summary[] | null;
editIndex: number | null;
editItem: Summary | null;
addingNew: boolean | null;
modifications: boolean;
isLoading: boolean;
}
The Summary model is this:
export class Summary {
@required()
title: string;
@required() // these decorators are for form validation
text: string;
@required() // these decorators are for form validation
focus: Focus[] = [];
@prop()
focusRef: DocumentReference[];
seqNo: number;
id: string;
}
the Focus model is this -
export class Focus {
@required()
name: string;
seqNo: number;
id: string;
}
The effect that passes data to this action is -
this.actions$.pipe(
ofType(readSummaryAction),
switchMap(() =>
this.service.list$.pipe(
map(list => {
console.log('This is the list ', list);
return readSummarySuccessAction({ list });
}),
catchError(() => of(readSummaryFailureAction())),
),
),
),
);
The reducer there I am trying to populate summaryList is like this -
on(
readSummarySuccessAction,
(state, action): SummaryStateInterface => {
const updatedSummaryList = [...state.summaryList].concat(
JSON.parse(JSON.stringify(action.list)),
);
return {
...state,
summaryList: updatedSummaryList,
),
};
},
),
The data passed for this action an array of 2 items (2) [{…}, {…}] 0: {title: "Resume", url: "resume", ionicIcon: "", customIcon: "./assets/portfolio.svg", open: false, …} 1: {title: "Database", url: "", ionicIcon: "", customIcon: "./assets/server.svg", open: false, …} length: 2 proto: Array(0)
One of these items is -
focus: Array(3)
0: {id: "focusId1", name: "Main", seqNo: 1}
1: {id: "focusId2", name: "CFD", seqNo: 2}
2: {id: "focusId3", seqNo: 4.5, name: "Web"}
length: 3
__proto__: Array(0)
focusRef: (3) [n, n, n] // Firebase document reference
id: "sum1"
seqNo: 2.5
text: "Versatile and detail-driven Mechanical Engineer with a wealth of experience and knowledge in the Thermal-Fluids area. "
title: "Professional Summary"
the error thrown are -
core.js:4197 ERROR TypeError: Cannot freeze
at Function.freeze (<anonymous>)
at freeze (http://localhost:8101/vendor.js:103583:12)
at http://localhost:8101/vendor.js:103603:17
at Array.forEach (<anonymous>)
at freeze (http://localhost:8101/vendor.js:103586:40)
at http://localhost:8101/vendor.js:103603:17
at Array.forEach (<anonymous>)
at freeze (http://localhost:8101/vendor.js:103586:40)
at http://localhost:8101/vendor.js:103603:17
at Array.forEach (<anonymous>)
UnsubscriptionErrorImpl {message: "2 errors occurred during unsubscription:↵1) TypeEr…: Cannot add property 0, object is not extensible", name: "UnsubscriptionError", errors: Array(2)}
core.js:4197 ERROR TypeError: Cannot assign to read only property '__zone_symbol__state' of object '[object Object]'
zone-evergreen.js:976 Uncaught TypeError: Cannot add property 0, object is not extensible
Is it possible to get some feedback ?
I am willing to restructure (flatten) the state - but to what and how, I don't know.
The focusRef property in the Summary class was a DocumentReference. Unfortunately for whatever reasons, DocumentReference field in Firebase has circular references.
The circular reference topic is discussed in this post : Firestore references create a "TypeError: Converting circular structure to JSON"
I converted these references (ref) to strings - using their path property (ref.path).
Once strings all these errors went away. I would welcome if someone could explain how freeze from core.js would work - It was throwing following error -
Unrelated but useful To detect circular references in an object (x) is: Do JSON.parse(JSON.stringify(x)). This expression will fail.