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 firebase from 'firebase/app'
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;

Alta de una colección dentro de otra colección

async (roomID, message) => db.collection('rooms').doc(roomID).collection('messages').add({ sender: 3, message });

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));

Ejercicio CRUD

Hacer el ejercicio del enlace, que cuenta con las funcionalidades de alta, baja, modificación y consulta de nombres de personas.

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 3
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 con email

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)
		}
	});
}, []);

Código versátil de firebase para hacer CRUD con diferentes entidades

import firebase, { db } from '../application/firebase';

/////////
// CREATE
/////////
export const addRootEntity = (entity, newValues) => db.collection(entity).add(newValues);

//collectionPath format: [{ collection: 'rooms', id: 'hasdu9ghw9' },{collection: 'message',},]
export const addPathEntity = (collectionPath, newValues) => {
    let path;
    let idIsPresent = false;
    collectionPath.forEach(({ collection, id }, n) => {
        const base = path || db;
        if (n == 0 && !id) {
            if (!idIsPresent) console.error('La id de la colección no está presente');
            return;
        }
        if (id) {
            idIsPresent = true;
            console.log(id);
            path = base.collection(collection).doc(id);
        } else {
            base.collection(collection).add(newValues);
        }
    })
}

///////
// READ
///////
export const getRootEntityById = (entity, id) => db.collection(entity).doc(id).get();

//conditions format: { googleId: 'aaaaaaaa' }
export const getRootEntityByConditions = (entity, conditions) => {
    let result = db.collection(entity);
    Object.keys(conditions).forEach(key => {
        result = result.where(key, '==', conditions[key]);
    });
    return result.get();
}

//collectionPath format: [{ collection: 'rooms', id: 'hasdu9ghw9' },{collection: 'message',},]
export const getPathEntityByConditions = (collectionPath, conditions) => {
    let path;
    let idIsPresent = false;
    return collectionPath.reduce((acc, { collection, id }, n) => {
        const base = path || db;
        if (n == 0 && !id) {
            console.log('first no id')
            if (!idIsPresent) console.error('La id de la colección no está presente');
            return;
        }
        if (id) {
            console.log('has id')
            idIsPresent = true;
            path = base.collection(collection).doc(id);
        } else {
            let result = base.collection(collection);
            Object.keys(conditions).forEach(key => {
                result = result.where(key, '==', conditions[key]);
            });
            return result.get();
        }
    }, {});
}

/////////
// UPDATE
/////////

export const updateRootEntityByFirebaseId = (entity, firebaseId, newValues) => db.collection(entity).doc(firebaseId).update(newValues);

export const updatePathEntityByConditions = (collectionPath, firebaseId, newValues) => {
    let path;
    let idIsPresent = false;
    collectionPath.forEach(({ collection, id }, n) => {
        const base = path || db;
        if (n == 0 && !id) {
            if (!idIsPresent) return;
        }
        if (id) {
            idIsPresent = true;
            path = base.collection(collection).doc(id);
        } else {
            base.collection(collection).doc(firebaseId).update(newValues);
        }
    });
}
///////////////
// LOGIN GOOGLE
///////////////

const provider = new firebase.auth.GoogleAuthProvider();

export const signInGoogle = () => firebase.auth().signInWithPopup(provider);
export const getUserByEmail = (email) => db.collection('users').where('email', '==', email).get();
export const addNewUser = (email) => db.collection('users').add({ email });

export const logInGoogleOrRegister = async () => {
    const useCredential = await signInGoogle();
    const email = useCredential.user.email;
    const users = await getUserByEmail(email);
    if (users.empty) {
        const user = await addNewUser(email);
        return user.id;
    } else {
        return users.docs[0].id;
    }
}

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();
}

← Compilar (build) una aplicación de React
Next JS →

Aviso Legal | Política de privacidad