This video is available to students only

Auth Effects and Firebase Initialization

We dispatched an event and wrote a handler. The handler returned an effects map, with a custom effect `:firebase/email-auth`. In this chapter, we'll create the custom effect handler and initialize the Firebase app.

Auth effects and Firebase initialization#

We dispatched an event and wrote a handler. The handler returned an effects map, with a custom effect :firebase/email-auth. In this chapter, we'll create the custom effect handler and initialize the Firebase app.

Create the effect handler#

Effect handlers are impure functions that can be used to perform side-effects like calling APIs, saving data to local storage, sending an email etc. In our case, the side-effect will log the user into Firebase and cache user details in app-db. The function re-frame.core/reg-fx can be used to register custom effects.

In smaller applications, you might have a namespace app.effects for all the effects. In our case, we are going to place this function in app.domain.firebase, since the effect is related to Firebase.

reg-fx accepts two arguments: an effect id and a handler function. Reframe calls the handler function with arguments passed to effect map.

To keep things in context, here is the event handler (built in the last chapter) that requested execution of this effect:

  • The event returned an effect map requesting to execute effect :firebase/email-auth with argument form-state, which is a map with keys :email and :password

  • The registered effect :firebase/email-auth's handler function is called with this map, which we destructure as {:keys [email password]}

  • The effect interacts with the Firebase SDK and calls the impure function signInWithEmailAndPassword. Notice the use of -> - the thread-first macro. The JS equivalent of the function call above is:

  • The sign-in function is impure because a remote resource is called

  • We also handle the error case and dispatch the ::email-auth-error event, which is again impure. We have not created a handler for ::email-auth-error yet

You might be wondering where the login success case is. Good observation! Firebase Auth expects us to register an "auth state observer" globally. Firebase also expects us to initialize a Firebase app globally.

Create Firebase auth state observer#

This observer function is called each time the auth state changes, ie when a user logs in or out. We will hook this observer in Reframe by dispatching events when the auth state changes. In real-world apps, this use case is similar to listening to sockets. A global listener waits for messages and dispatches Reframe events as messages are received.

Since this functionality is related to Firebase, we'll define the observer in the app.domain.firebase namespace:

  • we created a function observe-auth-state with defn-

  • the - hyphen suffix signifies a private function - ie this function can only be called in the current namespace

  • this function internally calls .onAuthStateChanged on (firebase/auth), the global Firebase Auth instance

  • a callback function is passed as the first argument

  • the callback receives a user object, which is a JavaScript object returned by Firebase when a user logs in or nil when the user logs out

  • depending on the existence of user, we dispatch the ::user-logged-in and ::user-logged-out events (which we haven't registered yet)

  • the function firebase-user->user converts the JS object to a Clojure map

Set up login error, success, and logout handlers#

The event handlers of the login and logout dispatch will add or remove this user from app-db. The login error handler will set the error message in app-db and unset the loading indicator. Let's define these handlers to save and remove the logged in user from app-db:

 

This page is a preview of Tinycanva: Clojure for React Developers

Please select a discussion on the left.