Firebase

Crear un proyecto de firebase

  1. Vamos a http://firebase.com/.
  2. Creamos un nuevo proyecto → Le ponemos un nombre.

Crear una base de datos en firebase

  1. Menu Build → Firestone.

Por hacer un simil con las bases de datos relacionales:

  • Cada collection equivaldría a una tabla.
  • Cada document equivaldría a un registro.
Firebase 1

Conexión con la estructura recien creada

npm i firebase

Configuramos las credenciales necesarias:

import * as firebase from 'firebase';
import '@firebase/auth';
import '@firebase/firestore';

export const firebaseConfig = {
    apiKey: 'AIzaSyDE4njjfYfOYf-Ghdg8QjA1yHTDWgKO9RM',
    authDomain: 'eldiariodepapa.firebaseapp.com',
    projectId: 'eldiariodepapa',
    storageBucket: "eldiariodepapa.appspot.com",
    databaseUrl: 'https://eldiariodepapa-default-rtdb.firebaseio.com/' // Para aplicaciones con en tiempo real
};

if(!firebase.apps.length){
    firebase.initializeApp(firebaseConfig);
}

export const db = firebase.firestore();
export default firebase;

Podemos obtener la projectId y el apiKey llendo a engranaje que esta al lado de Project Settings → General. Para que la API Key se visualiza tengo que haber inicializado la autentificación ( Firebase → Authentification → Get Started).

El authDomain será {ProjectId}.firebaseapp.com

Tendremos que configurar una regla para permitir la edición y consulta. Para ello iremos a Firestore → Rules →

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

CRUD en Firebase

import firebase, { db } from 'path/to/firebase';

Consulta:

De múltiples registros:

db.collection('books').get().then((querySnapshot) => {
     querySnapshot.forEach((doc) => {
          console.log(`${doc.id} => ${doc.data().title}`);
     });
});

De un solo registro:

const result = await db.collection('users').where('dni', '==', dni).get();
const author = result.docs[0].data();
const authorFirebaseRef = result.docs[0].id;

Alta:

const book = await db.collection('books').add({
     title: "Harry Potter",
     price: 22
});
const firebaseId = book.id;

Baja:

db.collection("books").doc("8NTTvwpuWpz6a4yxqczz").delete().then(res => console.log(res));

Modificación:

db.collection("books").doc("FkSp3s21g9yjF8LKkLFJ").update({ title: "harry" }).then(res => console.log(res));

Actualización de una referencia a un objeto

db.collection("users").doc(pacientFirebaseId).update({ doctorId: db.doc(`users/${user.firebaseId}`) }).then(res => console.log(res));

Cuando un usuario se loguea, comprobamos si está en la base de datos, si no está, lo damos de alta

const users= db.collection('users');

const snapshot = await users.where('uid', '==', user.uid).get();
if (snapshot.empty) {
    users.add({ email: user.email, uid: user.uid });
} else {
    console.log(snapshot);
}

Establecer relaciones entre colecciones

Para indicar que un autor tiene muchos libros, generalmente haremos subcolecciones, de tal forma que un autor tenga una subcolección de referencias a libros.

Firebase 2
const result = await authors.where('dni', '==', dni).get();
const author = result.docs[0].data(); 

db.collection('books').add({ title: 'ElQuijote', author: author.id });

Autentificación

Registro

const onSubmit = () => {
    firebase.auth().createUserWithEmailAndPassword(email, password)
    .then((userCredential) => { 
    setLoggedUser(userCredential.user)
    });
}

Login

const onLogin = () => {
	firebase.auth().signInWithEmailAndPassword(email, password)
	.then((userCredential) => {
		setLoggedUser(userCredential.user)
	});
}

Login con Google

Es necesario habilitar el provider en Google: Google Cloud → Authentification → Sign-in Method → Habilitamos Google

const SignInWithGoogle = () => {
	const provider = new firebase.auth.GoogleAuthProvider();

	firebase.auth().signInWithPopup(provider)
	.then((userCredential) => {
		console.log(userCredential);
	});
}

Logout

firebase.auth().signOut();

Comprobación de si el usuario está logueado

useEffect(() => {
	firebase.auth().onAuthStateChanged((user) => {
		if (user) {
			console.log(user)
		}
	});
}, []);

Real time database

Para hacer aplicaciones en tiempo real (por ejemplo, un chat).

En el momento de hacer esta documentación, la base de datos de la región de Bélgica está en Beta, así que es recomendable que uses la de U.S.

npm i @react-firebase/database
import firebase from 'firebase/app';
import "firebase/database";
import { FirebaseDatabaseProvider, FirebaseDatabaseNode, FirebaseDatabaseMutation } from "@react-firebase/database";
const firebaseConfig = {
    ...   
    databaseUrl: 'https://eldiariodepapa-default-rtdb.firebaseio.com/'
};
<FirebaseDatabaseProvider firebase={firebase} {...config}>
	<FirebaseDatabaseNode path="users/" limit={2} orderByKey>
	{(d, ...params) => {
    		console.log(d, params);
		return (
        		<>
            			<pre>Path {d.path}</pre>
				{d.value && (
                                	Object.entries(d.value).map(([id, value]) => <span>{value}</span>)
                		)}
			</>
		);
	}}
	</FirebaseDatabaseNode>
	<FirebaseDatabaseMutation type="push" path="messages/">
                    {({ runMutation }) => (
                        <button onClick={() => runMutation({ user: 'A', message: 'Hola' })}>Push</button>
                    )}
	</FirebaseDatabaseMutation>
</FirebaseDatabaseProvider>

Subir una imagen a firebase

import { firebase } from '../../../database/firebase';
import uuid from 'react-native-uuid';
import { uploadImageAsync } from '../../cloud/uploadphoto';

export default (props) => {
    const uploadPhoto = async (imgPathInServer) => {
        let uploadUrl = "";
        try {
            if (props.info.photoUri != null) {
                uploadUrl = await uploadImageAsync(props.info.photoUri, imgPathInServer);
            }
        } catch (e) {
            console.log(e);
        } finally {
            console.log({ uploading: false });
        }
        updateURL(id, uploadUrl);
    }

    const updateURL = async (id, photoURL) => {
        const dbRef = firebase
            .firestore()
            .collection('users')
            .doc(id);

        try {
            dbRef.update({
                photoProfile: photoURL,
            })
        } catch (e) {
            console.log(e);
            alert('Updated photoURL error');
        }
    }

async function uploadImageAsync(uri, imgPathInServer) {
    const blob = await new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.onload = function() {
            resolve(xhr.response);
        };
        xhr.onerror = function(e) {
            console.log(e);
            reject(new TypeError('Network request failed'));
        };
        xhr.responseType = 'blob';
        xhr.open('GET', uri, true);
        xhr.send(null);
    });

    const ref = firebase
        .storage()
        .ref()
        .child(`${imgPathInServer}/${uuid.v4()}`);
    const snapshot = await ref.put(blob);

    blob.close();
    return await snapshot.ref.getDownloadURL();
}

← Observer Pattern
Next JS →

Aviso Legal | Política de privacidad