You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Angular Ngrx Effects With the Firebase Realtime Database
Episode 44 written by Jeff DelaneyIf you’re brand new to Redux patterns in Angular, check out the NgRx Quick Start Lesson before diving into this lesson. It covers the basic concepts that this article only brushes over.
In this lesson, we will integrate the Firebase Realtime Database with @ngrx/effects for Angular 4. The app itself is very simple - it retrieves a post from Firebase and allows the user to update it’s vote total by upvoting or downvoting it . You can obtain the full source code for ngrx-fire on github. The goal is not to build a real-world app, but rather show you how ngrx effects can be used with Firebase.
This lesson assumes you have a basic Angular app generated with the Angular CLI with AngularFire2 configured as the backend.
NgRx Effects Overview
Effects are used in Redux to handle the side effects of impure functions that affect data outside their scope - such as requests to the Firebase Database. When performing operations in Firebase, we get a Promise that will either succeed or fail. That means we have at least three possible states for a Firebase operation, such as LOADING, SUCCESS, or FAIL. Ngrx effects gives us a way reconcile the side effects of these various states throughout the course of an API call.
Pure Functions vs Impure Functions
To get a better idea of this concept, let’s compare pure and impure functions in JavaScript.
A return value of a pure function is affected only by its own logic and arguments. Consider the following example:
const pure = (hello) => { |
Now lets write an impure function. Notice how it takes the value of variable outside of its scope to create it’s return value.
let hello = 'Howdy!'; |
In app development, most impure function are the result of callbacks, Promises, making calls external APIs, or changing data in some other asynchronous process.
const impure = () => { |
Building an NgRx App with Firebase
This section will cover four different elements of an ngrx Redux app, including the model, actions, reducer, and effects.
app.module.ts
First things first, let’s get import the necessary ngrx pieces in the NgModule.
import { environment } from '../environments/environment'; |
post.model.ts
Our post model is just a TypeScript interface that will serve as the blueprint for our Post data. When working with ngrx, it is highly recommended to that you model your data with TypeScript interfaces to ensure the app data store adheres to the intended structure.
export interface Post { |
post.actions.ts
The only way to change the state of ngrx Store
is by dispatching an action. In this example, we are giving each action its own class along with a payload
in the constructor
. This allows us to send a data payload to the action.
import { Action } from '@ngrx/store'; |
post.reducer.ts
The reducer function is pretty simple. It just creates a new object by copying the old state, then overwriting any properties that have changed. It updates the data payload when necessary and toggles the loading
property.
Our reducer takes advantage of the spread syntax in JavaScript compose a new state object, i.e { ...oldState, ...newValues }
. This syntax is an alternative to Object.assign
.
import * as PostActions from '../actions/post.actions'; |
post.effects.ts
The purpose of ngrx/effects is to merge action streams, making it possible for you to subscribe to them. It does this by exporting an Actions
observable that emits all actions dispatched in the app.
For example, the calling actions.ofType('VOTE_UPDATE')
will set that action as the root, then it will emit the other actions VOTE_SUCCESS or VOTE_FAIL as they occur asynchronously.
I am using the RxJS delay(2000)
to show the loading spinner, but is not required for the code to work. Firebase is too fast, so I manually added a delay.
import { Injectable } from '@angular/core'; |
Putting It Together in the App Component
Now that all of the ngrx code is in place, we just need to give the user a way interact with it in the UI in Angular.
app.component.ts
We can retrieve a post from Firebase and update it in the ngrx store by simply dispatching root action.
import { Component } from '@angular/core'; |
app.component.html
In the html, we can just subscribe to the post and attach the dispatch functions to button clicks. I am also using FontAwesome to display a loading spinner when the post state is loading.
<div *ngIf="post$ | async as post"> |
Up Next
I plan on producing another ngrx lesson that will cover Firebase Auth with ngrx in the near future. If you have suggestions, please let me know in the comments or via our Slack team.