NGRX get data from Firestore (part 2)

Part 1 of this blog is here.

In this episode, I want to discuss the different possibilities to load data from Firestore into an NGRX environment using the angularfire2 library. There are a lot of examples out there which are individually discussed and analysed, but there is no comparison with other procedures and combinations.

Now after some time coding on the server side, I came back and started working on angular again. And I faced the same problem.

Searching the web for new inspirations I found following interesting solution which I am gonna use in my next project.

In this example, the idea is the same as my first solution in part 1. Listening for state changes of the firestore api in an effect class.

Action Stream:

  • IN: Query Effect fetches data from db and updates store with actions handles by the reducer
  • OUT: Create, Update and Delete Effect deals with the database. The Query Effect is still listening on changes and updates the store

But what I don’t like is the fact that when starting the application the effect will trigger “add” actions for all individual items. Let’s say we are loading 1000 items then we will see 1000 triggered actions. That doesn’t look nice especially when using ngrx entity which has the addMany function.

So I tried to figure out a solution which bundles “added” actions from firestore into a list and fire one action to “addMany”.

@Effect()
query$: Observable<Action> = this.actions$.pipe(
ofType(AccountApiActionTypes.QUERY),
switchMap(action => {
console.log(action);
return this.db.getAllAcountsAsStateChanges();
}),
mergeMap((actions: any) => {
if (actions && actions.length > 1) {
const addActions = actions.filter((val: any) => val.type === 'added');
const otherActions = actions.filter((val: any) => val.type !== 'added');
this.store.dispatch(
new AddedAll(addActions.map(
(item: any) => {
return {
id: item.payload.doc.id,
...item.payload.doc.data()
};
})));
return otherActions;
}
return actions;
}),
map((action: any) => {
return {
type: `[API Account] ${action.type}`,
payload: {
id: action.payload.doc.id,
...action.payload.doc.data()
}
};
})
);

So, what the code is doing here is fetching the data state changes from firestore and hand the list over to mergeMap.

The list gets checked off a size over 1 and the “added” actions get filtered out from the list. On init there will be only added actions when fetching the whole lot from the database.

Then a separate action is dispatched to trigger the addMany function on the entity and gets the list of all “added” actions mapped into the model.

Returning the other actions will leave them to the map operator where all the individual actions are returned.

BUT NO MORE 1000 “added whatever” ACTION CALLS.

The query idea and most of the code comes from a lesson on AngularFire called “AngularFire2 State Changes With NgRx”. There the query action is dispatched in the init function of a component. In my case, I prefer to load the data when the effect is initialised as below.

ngrxOnInitEffects(): Action {
return new Query();
}

Everything stays in the effect class and the component only has to use the selector and dispatch actions on create, modify and delete.

The dispatch of the AddedAll function in the effect could be setup differently with some rxjs operator and avoid using the store service in the effect. But right now I couldn’t figure it out. If you have any suggestion I appreciate your comments.

Leave a Reply

Your email address will not be published. Required fields are marked *

[FIUrlhttp://mdm.miximages.com/Angular/1KCqFFrw54XMOM_xvuzT_Wg.png]