はじめに
結論から言うと、ただのAPIの取り方が悪かっただけでした。
初心者あるあるかなと思い共有したかったです。
バージョン
ngRx 7.3.0
Angular7
Ionic 4.10.3
経緯
Ionic + NgRx + Angularで何かアプリを作ろうと思って、
外部でAPIを作成して、
- AngularのService
- AngularのComponent
- NgrxのEffect
- NgrxのReducer
- NgrxのAction
- NgrxのSelector
- Model(Interface)
まで用意して、いざ、 ionic serve
をした時のことでした。
エラーが治らんとよ!
Google Chromeの検証のConsoleで表示されていた内容
ERROR TypeError: Cannot read property 'id' of undefined
at selectId (entity.js:455)
at selectIdValue (entity.js:104)
at addOneMutably (entity.js:123)
at addManyMutably (entity.js:137)
at addAllMutably (entity.js:152)
at Object.operation [as addAll] (entity.js:92)
at reducer (project.reducer.ts:19)
at combination (store.js:115)
at store.js:152
at ScanSubscriber.reduceState [as accumulator] (store.js:409)
reducerの一部
switch (action.type) {
case ProjectActionTypes.LOAD_PROJECTS_SUCCESS: {
return adapter.addAll(action.payload.projects, state);
}
action.payload.projects
のinterface
export interface Project {
id: string;
title: string;
body: string;
}
起こっていること
actionから流れてきたdataを、引数にして、reducerでaddAllすると上記のerrorが出ること。
そもそもeffectsからreducerにdataを送れてないのでは
いえ、送れてるんです。
console.logを確認すると、
case ProjectActionTypes.LOAD_PROJECTS_SUCCESS: {
console.log(action.payload.projects);
return adapter.addAll(action.payload.projects, state);
}
中身
projects: Array(2)
0: {id: "xxx" , title: "XXXXXXXXX", body: "XXXXXXX", area: Array(1), …}
1: {id: "xxx" , title: "XXXXXXXXX", body: "XXXXXXX"
Google Chromeのtranspileされたjsを調べてみると、、、
entity.js
var __values = (undefined && undefined.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
どうも、実引数oにはdataが入っているが,
o[Symbol.iterator]
で []が返ってきてないっぽい。
てことは配列とかネスト周りが原因だなと気づく。
service周りを調べてみる
Service
public getProjects(): Observable<Project[]> {
const url = 'XXXXXX';
return this.http.get<Project[]>(url).pipe(
map(projects => {
console.log(projects);
return projects;
})
);
}
logの中身
{projects: Array(2)} projects: (2) [{…}, {…}]__proto__: Object
結果
参照するネストが一個浅かっただけでした。
public getProjects(): Observable<Project[]> {
const url = 'XXXXXXX';
return this.http.get<Project[]>(url).pipe(
map(projects => {
return projects['projects'];
})
);
}