IjzerenHein / firestorter

Use Google Firestore in React with zero effort, using MobX 🤘
http://firestorter.com
MIT License
378 stars 50 forks source link

Change document ref on the fly? #150

Closed SrBrahma closed 2 years ago

SrBrahma commented 2 years ago

I am considering using this lib, instead of doing the mobx by hand.

But, lets say that I, an User, just logged in. I want my ref to be set to my users/uid. But what to do when I logout and login, changing user uid? How to handle both cases, specially when the user is no longer logged?

IjzerenHein commented 2 years ago

Yeah that's super easy to do. I usually have an Auth helper class that listens to auth changes and sets an observable accordingly. You can then use that observable in your document source function (which should return a ref or a field-path), which then automatically updates the document ref when your auth changes.

import { Document } from 'firestorter';
import { Auth } from './Auth';

const doc = new Document(() => Auth.getInstance().user ? `mycollection/${Auth.getInstance().userId}` : null);
Auth.ts ```ts import { observable, runInAction } from 'mobx'; import { firebase } from '../firebase'; export class Auth { private readonly auth = firebase.auth(); private mutableUser = observable.box(firebase.auth().currentUser); private mutableIsLoading = observable.box(true); private readonly displayName = observable.box(firebase.auth().currentUser?.displayName ?? ''); private readonly idTokenResult = observable.box(); private static instance?: Auth; static getInstance(): Auth { this.instance = this.instance ?? new Auth(); return this.instance; } constructor() { this.auth.onAuthStateChanged((firebaseUser: firebase.User | null) => { runInAction(() => { this.mutableUser.set(firebaseUser); this.displayName.set(firebaseUser?.displayName ?? ''); if (!firebaseUser) this.idTokenResult.set(undefined); this.mutableIsLoading.set(false); }); }); } get isLoading() { return this.mutableIsLoading.get(); } get user(): firebase.User | null { return this.mutableUser.get(); } get userId(): string { return this.user?.uid ?? ''; } get userName(): string | null { if (this.mutableUser.get()) { return this.displayName.get() || null; } else { return null; } } getIdToken() { return this.auth.currentUser?.getIdToken(); } private get tokenResult(): firebase.auth.IdTokenResult | undefined { if (this.isLoading) { return undefined; } const token = this.idTokenResult.get(); if (token || !this.auth.currentUser) { return token; } this.auth.currentUser.getIdTokenResult().then( (token) => runInAction(() => this.idTokenResult.set(token)), (error) => { console.error(`Failed to obtain user token, error: ${error.message}`); } ); return undefined; } get isAdmin(): boolean { return this.tokenResult?.claims.admin ?? false; } async updateProfile(profile: any) { // @ts-ignore TODO await firebase.auth().currentUser.updateProfile(profile); if (profile.displayName) { runInAction(() => { this.displayName.set(profile.displayName); }); } } } ```