Integre Firebase con una aplicación Next.js

1. Antes de comenzar

En este codelab, aprenderá cómo integrar Firebase con una aplicación web Next.js llamada Friendly Eats, que es un sitio web para reseñas de restaurantes.

Aplicación web Friendly Eats

La aplicación web completa ofrece funciones útiles que demuestran cómo Firebase puede ayudarte a crear aplicaciones Next.js. Estas características incluyen lo siguiente:

  • Iniciar sesión con Google y cerrar sesión: la aplicación web completa le permite iniciar sesión con Google y cerrar sesión. El inicio de sesión y la persistencia del usuario se administran completamente a través de Firebase Authentication .
  • Imágenes: la aplicación web completa permite a los usuarios registrados cargar imágenes de restaurantes. Los recursos de imagen se almacenan en Cloud Storage para Firebase . El SDK de JavaScript de Firebase proporciona una URL pública para las imágenes cargadas. Esta URL pública luego se almacena en el documento del restaurante correspondiente en Cloud Firestore .
  • Reseñas: la aplicación web completa permite a los usuarios registrados publicar reseñas de restaurantes que consisten en una calificación de estrellas y un mensaje de texto. La información de la revisión se almacena en Cloud Firestore.
  • Filtros: la aplicación web completa permite a los usuarios registrados filtrar la lista de restaurantes según categoría, ubicación y precio. También puede personalizar el método de clasificación utilizado. Se accede a los datos desde Cloud Firestore y las consultas de Firestore se aplican según los filtros utilizados.

Requisitos previos

  • Conocimiento de Next.js y JavaScript.

lo que aprenderás

  • Cómo usar Firebase con Next.js App Router y renderizado del lado del servidor.
  • Cómo conservar imágenes en Cloud Storage para Firebase.
  • Cómo leer y escribir datos en una base de datos de Cloud Firestore.
  • Cómo utilizar el inicio de sesión con Google con el SDK de JavaScript de Firebase.

Lo que necesitarás

  • git
  • El kit de desarrollo de Java
  • Una versión estable reciente de Node.js
  • Un navegador de tu elección, como Google Chrome
  • Un entorno de desarrollo con un editor de código y terminal.
  • Una cuenta de Google para la creación y gestión de tu proyecto Firebase
  • La capacidad de actualizar su proyecto de Firebase al plan de precios de Blaze

2. Configure su entorno de desarrollo

Este codelab proporciona el código base inicial de la aplicación y se basa en Firebase CLI.

Descargar el repositorio

  1. En tu terminal, clona el repositorio GitHub del codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. El repositorio de GitHub contiene proyectos de muestra para múltiples plataformas. Sin embargo, este codelab utiliza solo el directorio nextjs-start . Tome nota de los siguientes directorios:
    • nextjs-start : contiene el código de inicio sobre el que construye.
    • nextjs-end : contiene el código de solución para la aplicación web terminada.
  3. En su terminal, navegue hasta el directorio nextjs-start e instale las dependencias necesarias:
    cd friendlyeats-web/nextjs-start
    npm install
    

Instalar o actualizar Firebase CLI

Ejecute el siguiente comando para verificar que tenga Firebase CLI instalado y que sea v12.5.4 o superior:

firebase --version
  • Si tiene Firebase CLI instalado, pero no es la versión 12.5.4 o superior, actualícela:
    npm update -g firebase-tools
    
  • Si no tiene Firebase CLI instalado, instálelo:
    npm install -g firebase-tools
    

Si no puede instalar Firebase CLI debido a errores de permisos, consulte la documentación de npm o use otra opción de instalación .

Iniciar sesión en Firebase

  1. Ejecute el siguiente comando para iniciar sesión en Firebase CLI:
    firebase login
    
  2. Dependiendo de si desea que Firebase recopile datos, ingrese Y o N
  3. En su navegador, seleccione su cuenta de Google y luego haga clic en Permitir .

3. Configura tu proyecto de Firebase

En esta sección, configurará un proyecto de Firebase y le asociará una aplicación web de Firebase. También configurará los servicios de Firebase utilizados por la aplicación web de muestra.

Crear un proyecto de Firebase

  1. En Firebase console , haz clic en Crear proyecto .
  2. En el cuadro de texto Ingrese el nombre de su proyecto , ingrese FriendlyEats Codelab (o el nombre de un proyecto de su elección) y luego haga clic en Continuar .
  3. Para este codelab, no necesita Google Analytics, así que desactive la opción Habilitar Google Analytics para este proyecto .
  4. Haga clic en Crear proyecto .
  5. Espere a que se aprovisione su proyecto y luego haga clic en Continuar .
  6. En su proyecto de Firebase, vaya a Configuración del proyecto . Anota el ID de tu proyecto porque lo necesitarás más adelante. Este identificador único es la forma en que se identifica su proyecto (por ejemplo, en Firebase CLI).

Agrega una aplicación web a tu proyecto de Firebase

  1. Navegue a la descripción general de su proyecto en su proyecto de Firebase y luego haga clic en e41f2efdd9539c31.png Web .
  2. En el cuadro de texto Apodo de la aplicación , ingrese un apodo memorable para la aplicación, como My Next.js app
  3. Seleccione la casilla Configurar también Firebase Hosting para esta aplicación .
  4. Haga clic en Registrar aplicación > Siguiente > Siguiente > Continuar a la consola .

Actualice su plan de precios de Firebase

Para usar marcos web, su proyecto de Firebase debe estar en el plan de precios de Blaze , lo que significa que está asociado con una cuenta de facturación de Cloud .

Sin embargo, tenga en cuenta que la finalización de este codelab no debería generar ningún cargo real.

Para actualizar su proyecto al plan Blaze, siga estos pasos:

  1. En Firebase console, selecciona actualizar tu plan .
  2. En el cuadro de diálogo, seleccione el plan Blaze y luego siga las instrucciones en pantalla para asociar su proyecto con una cuenta de facturación de Cloud.
    Si necesitabas crear una cuenta de facturación de Cloud, es posible que tengas que volver al flujo de actualización en Firebase console para completar la actualización.

Configurar los servicios de Firebase en la consola de Firebase

Configurar la autenticación

  1. En Firebase console, navega hasta Autenticación .
  2. Haga clic en Comenzar .
  3. En la columna Proveedores adicionales , haga clic en Google > Habilitar .
  4. En el cuadro de texto Nombre público del proyecto , ingrese un nombre fácil de recordar, como My Next.js app
  5. En el menú desplegable Correo electrónico de soporte para el proyecto , seleccione su dirección de correo electrónico.
  6. Clic en Guardar .

Configurar Cloud Firestore

  1. En Firebase console, navega hasta Firestore .
  2. Haga clic en Crear base de datos > Iniciar en modo de prueba > Siguiente .
    Más adelante en este codelab, agregará reglas de seguridad para proteger sus datos. No distribuya ni exponga una aplicación públicamente sin agregar reglas de seguridad para su base de datos.
  3. Utilice la ubicación predeterminada o seleccione una ubicación de su elección.
    Para una aplicación real, debes elegir una ubicación que esté cerca de tus usuarios. Tenga en cuenta que esta ubicación no se puede cambiar más adelante y también será automáticamente la ubicación de su depósito predeterminado de Cloud Storage (siguiente paso).
  4. Haga clic en Listo.

Configurar almacenamiento en la nube para Firebase

  1. En Firebase console, navega hasta Almacenamiento .
  2. Haga clic en Comenzar > Iniciar en modo de prueba > Siguiente .
    Más adelante en este codelab, agregará reglas de seguridad para proteger sus datos. No distribuya ni exponga una aplicación públicamente sin agregar reglas de seguridad para su depósito de almacenamiento.
  3. La ubicación de su depósito ya debería estar seleccionada (debido a la configuración de Firestore en el paso anterior).
  4. Haga clic en Listo.

4. Revise el código base inicial

En esta sección, revisará algunas áreas del código base de inicio de la aplicación a las que agregará funcionalidad en este codelab.

Estructura de carpetas y archivos

La siguiente tabla contiene una descripción general de la estructura de carpetas y archivos de la aplicación:

Carpetas y archivos

Descripción

src/components

Componentes de React para filtros, encabezados, detalles de restaurantes y reseñas

src/lib

Funciones de utilidad que no están necesariamente vinculadas a React o Next.js

src/lib/firebase

Código específico de Firebase y configuración de Firebase

public

Activos estáticos en la aplicación web, como íconos

src/app

Enrutamiento con el enrutador de la aplicación Next.js

src/app/restaurant

Un controlador de ruta API

package.json y package-lock.json

Dependencias del proyecto con npm

next.config.js

Configuración específica de Next.js (las acciones del servidor están habilitadas )

jsconfig.json

Configuración del servicio de lenguaje JavaScript

Componentes de servidor y cliente

La aplicación es una aplicación web Next.js que utiliza App Router . La representación del servidor se utiliza en toda la aplicación. Por ejemplo, el archivo src/app/page.js es un componente del servidor responsable de la página principal. El archivo src/components/RestaurantListings.jsx es un componente del cliente indicado por la directiva "use client" al principio del archivo.

Declaraciones de importación

Es posible que observe declaraciones de importación como las siguientes:

import RatingPicker from "@/src/components/RatingPicker.jsx";

La aplicación utiliza el símbolo @ para evitar rutas de importación relativas complicadas y es posible gracias a los alias de ruta .

API específicas de Firebase

Todo el código de la API de Firebase está incluido en el directorio src/lib/firebase . Los componentes individuales de React luego importan las funciones empaquetadas desde el directorio src/lib/firebase , en lugar de importar funciones de Firebase directamente.

datos simulados

Los datos de reseñas y restaurantes simulados están contenidos en el archivo src/lib/randomData.js . Los datos de ese archivo se ensamblan en el código del archivo src/lib/fakeRestaurants.js .

5. Configure el alojamiento local con el emulador de Firebase Hosting

En esta sección, utilizará el emulador de Firebase Hosting para ejecutar la aplicación web Next.js localmente.

Al final de esta sección, el emulador de Firebase Hosting ejecuta la aplicación Next.js por usted, por lo que no necesita ejecutar Next.js en un proceso separado de los emuladores.

Descargar y usar una cuenta de servicio de Firebase

La aplicación web que crearás en este codelab utiliza la representación del lado del servidor con Next.js.

El SDK de Firebase Admin para Node.js se utiliza para garantizar que las reglas de seguridad funcionen desde el código del lado del servidor. Para usar las API en Firebase Admin, debe descargar y usar una cuenta de servicio de Firebase desde Firebase console.

  1. En Firebase console, navega hasta la página Cuentas de servicio en la configuración de tu proyecto .
  2. Haga clic en Generar nueva clave privada > Generar clave .
  3. Una vez que el archivo se haya descargado en su sistema de archivos, obtenga la ruta completa a ese archivo.
    Por ejemplo, si descargó el archivo en su directorio de Descargas , la ruta completa podría verse así: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. En su terminal, configure la variable de entorno GOOGLE_APPLICATION_CREDENTIALS en la ruta de su clave privada descargada. En un entorno Unix, el comando podría verse así:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Mantenga esta terminal abierta y úsela durante el resto de este codelab, ya que su variable de entorno podría perderse si inicia una nueva sesión de terminal.
    Si abre una nueva sesión de terminal, debe volver a ejecutar el comando anterior.

Agregue su configuración de Firebase al código de su aplicación web

  1. En Firebase console, navega hasta la configuración de tu proyecto .
  2. En el panel de instalación y configuración del SDK , busque la variable firebaseConfig y copie sus propiedades y sus valores.
  3. Abra el archivo .env en su editor de código y complete los valores de las variables de entorno con los valores de configuración de Firebase console.
  4. En el archivo, reemplace las propiedades existentes con las que copió.
  5. Guarda el archivo.

Inicializa la aplicación web con tu proyecto de Firebase

Para conectar la aplicación web a su proyecto de Firebase, siga estos pasos:

  1. En su terminal, asegúrese de que los marcos web estén habilitados en Firebase:
    firebase experiments:enable webframeworks
    
  2. Inicializar Firebase:
    firebase init
    
  3. Seleccione las siguientes opciones:
    • Firestore: configure reglas de seguridad e indexe archivos para Firestore
    • Alojamiento: configure archivos para Firebase Hosting y (opcionalmente) configure implementaciones de GitHub Action
    • Almacenamiento: configurar un archivo de reglas de seguridad para Cloud Storage
    • Emuladores: configurar emuladores locales para productos Firebase
  4. Seleccione Usar un proyecto existente y luego ingrese el ID del proyecto que anotó anteriormente.
  5. Seleccione los valores predeterminados para todas las preguntas posteriores hasta llegar a la pregunta ¿En qué región le gustaría alojar contenido del lado del servidor, si corresponde? . La terminal muestra un mensaje que detecta una base de código Next.js existente en el directorio actual.
  6. Para la pregunta ¿En qué región le gustaría alojar contenido del lado del servidor, si corresponde? , seleccione la ubicación que seleccionó previamente para Firestore y Cloud Storage.
  7. Seleccione los valores predeterminados para todas las preguntas posteriores hasta llegar a la pregunta ¿Qué emuladores de Firebase desea configurar? . Para esta pregunta, seleccione Emulador de funciones y Emulador de hosting .
  8. Seleccione los valores predeterminados para todas las demás preguntas.

Implementar reglas de seguridad

El código ya tiene conjuntos de reglas de seguridad para Firestore y Cloud Storage para Firebase. Después de implementar las reglas de seguridad, los datos de su base de datos y su depósito estarán mejor protegidos contra el uso indebido.

  1. Para implementar estas reglas de seguridad, ejecute este comando en su terminal:
    firebase deploy --only firestore:rules,storage
    
  2. Si se le pregunta: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" , seleccione .

Inicie el emulador de hosting

  1. En su terminal, inicie el emulador de Hosting:
    firebase emulators:start --only hosting
    
    Su terminal responde con el puerto donde puede encontrar el emulador de Hosting, por ejemplo http://localhost:5000/ .

Terminal que muestra que el emulador de hosting está listo

  1. En su navegador, navegue hasta la URL con el emulador de Firebase Hosting.
  2. Si ve el error en la página web que comienza así: "Error: Firebase session cookie has incorrect..." , debe eliminar todas las cookies en su entorno localhost. Para ello, siga las instrucciones en eliminar cookies | Documentación de herramientas de desarrollo .

Un error de sesión de cookies

Eliminar cookies en DevTools

¡Ahora puedes ver la aplicación web inicial! Aunque estés viendo la aplicación web en una URL de host local, utiliza servicios reales de Firebase que configuraste en tu consola.

6. Agregue autenticación a la aplicación web.

En esta sección, agrega autenticación a la aplicación web para poder iniciar sesión en ella.

Implementar las funciones de inicio y cierre de sesión.

  1. En el archivo src/lib/firebase/auth.js , reemplace las funciones onAuthStateChanged , signInWithGoogle y signOut con el siguiente código:
export function onAuthStateChanged(cb) {
        return _onAuthStateChanged(auth, cb);
}

export async function signInWithGoogle() {
        const provider = new GoogleAuthProvider();

        try {
                await signInWithPopup(auth, provider);
        } catch (error) {
                console.error("Error signing in with Google", error);
        }
}

export async function signOut() {
        try {
                return auth.signOut();
        } catch (error) {
                console.error("Error signing out with Google", error);
        }
}

Este código utiliza las siguientes API de Firebase:

API de base de fuego

Descripción

GoogleAuthProvider

Crea una instancia del proveedor de autenticación de Google.

signInWithPopup

Inicia un flujo de autenticación basado en diálogo.

auth.signOut

Cierra la sesión del usuario.

En el archivo src/components/Header.jsx , el código ya invoca las funciones signInWithGoogle y signOut .

  1. En la aplicación web, actualice la página y haga clic en Iniciar sesión con Google . La aplicación web no se actualiza, por lo que no está claro si el inicio de sesión se realizó correctamente.

Suscríbete a los cambios de autenticación

Para suscribirse a los cambios de autenticación, siga estos pasos:

  1. Navegue hasta el archivo src/components/Header.jsx .
  2. Reemplace la función useUserSession con el siguiente código:
function useUserSession(initialUser) {
        // The initialUser comes from the server through a server component
        const [user, setUser] = useState(initialUser);
        const router = useRouter();

        useEffect(() => {
                const unsubscribe = onAuthStateChanged(authUser => {
                        setUser(authUser);
                });
                return () => {
                        unsubscribe();
                };
        }, []);

        useEffect(() => {
                onAuthStateChanged(authUser => {
                        if (user === undefined) return;
                        if (user?.email !== authUser?.email) {
                                router.refresh();
                        }
                });
        }, [user]);

        return user;
}

Este código utiliza un enlace de estado de React para actualizar al usuario cuando la función onAuthStateChanged especifica que hay un cambio en el estado de autenticación.

Verificar cambios

El diseño raíz en el archivo src/app/layout.js representa el encabezado y pasa al usuario, si está disponible, como accesorio.

<Header initialUser={currentUser?.toJSON()} />

Esto significa que el componente <Header> representa los datos del usuario, si están disponibles, durante el tiempo de ejecución del servidor. Si hay actualizaciones de autenticación durante el ciclo de vida de la página después de la carga inicial, el controlador onAuthStateChanged las maneja.

Ahora es el momento de probar la aplicación web y verificar lo que creó.

Para verificar el nuevo comportamiento de autenticación, siga estos pasos:

  1. En su navegador, actualice la aplicación web. Su nombre para mostrar aparece en el encabezado.
  2. Cierra sesión y vuelve a iniciar sesión. La página se actualiza en tiempo real sin necesidad de actualizar la página. Puedes repetir este paso con diferentes usuarios.
  3. Opcional: haga clic con el botón derecho en la aplicación web, seleccione Ver código fuente de la página y busque el nombre para mostrar. Aparece en la fuente HTML sin formato devuelta por el servidor.

7. Ver información del restaurante

La aplicación web incluye datos simulados de restaurantes y reseñas.

Añadir uno o más restaurantes

Para insertar datos de restaurantes simulados en su base de datos local de Cloud Firestore, siga estos pasos:

  1. En la aplicación web, seleccione 2cf67d488d8e6332.png > Agregar restaurantes de muestra .
  2. En Firebase console, en la página de la base de datos de Firestore , selecciona restaurantes . Verá los documentos de nivel superior en la colección de restaurantes, cada uno de los cuales representa un restaurante.
  3. Haga clic en algunos documentos para explorar las propiedades de un documento de restaurante.

Mostrar la lista de restaurantes

Su base de datos de Cloud Firestore ahora tiene restaurantes que la aplicación web Next.js puede mostrar.

Para definir el código de obtención de datos, siga estos pasos:

  1. En el archivo src/app/page.js , busque el componente del servidor <Home /> y revise la llamada a la función getRestaurants , que recupera una lista de restaurantes en tiempo de ejecución del servidor. Implementará la función getRestaurants en los siguientes pasos.
  2. En el archivo src/lib/firebase/firestore.js , reemplace las funciones applyQueryFilters y getRestaurants con el siguiente código:
function applyQueryFilters(q, { category, city, price, sort }) {
        if (category) {
                q = query(q, where("category", "==", category));
        }
        if (city) {
                q = query(q, where("city", "==", city));
        }
        if (price) {
                q = query(q, where("price", "==", price.length));
        }
        if (sort === "Rating" || !sort) {
                q = query(q, orderBy("avgRating", "desc"));
        } else if (sort === "Review") {
                q = query(q, orderBy("numRatings", "desc"));
        }
        return q;
}

export async function getRestaurants(filters = {}) {
        let q = query(collection(db, "restaurants"));

        q = applyQueryFilters(q, filters);
        const results = await getDocs(q);
        return results.docs.map(doc => {
                return {
                        id: doc.id,
                        ...doc.data(),
                        // Only plain objects can be passed to Client Components from Server Components
                        timestamp: doc.data().timestamp.toDate(),
                };
        });
}
  1. Actualiza la aplicación web. Las imágenes de restaurantes aparecen como mosaicos en la página.

Verifique que los listados de restaurantes se carguen en tiempo de ejecución del servidor

Al utilizar el marco Next.js, es posible que no sea obvio cuándo se cargan los datos en tiempo de ejecución del servidor o en tiempo de ejecución del lado del cliente.

Para verificar que los listados de restaurantes se carguen en tiempo de ejecución del servidor, siga estos pasos:

  1. En la aplicación web, abra DevTools y desactive JavaScript .

Deshabilitar JavaScipt en DevTools

  1. Actualiza la aplicación web. Los listados de restaurantes aún se cargan. La información del restaurante se devuelve en la respuesta del servidor. Cuando JavaScript está habilitado, la información del restaurante se hidrata a través del código JavaScript del lado del cliente.
  2. En DevTools, vuelva a habilitar JavaScript .

Escuche las actualizaciones de los restaurantes con los oyentes de instantáneas de Cloud Firestore

En la sección anterior, vio cómo se cargó el conjunto inicial de restaurantes desde el archivo src/app/page.js . El archivo src/app/page.js es un componente del servidor y se representa en el servidor, incluido el código de obtención de datos de Firebase.

El archivo src/components/RestaurantListings.jsx es un componente del cliente y se puede configurar para hidratar el marcado renderizado por el servidor.

Para configurar el archivo src/components/RestaurantListings.jsx para hidratar el marcado renderizado por el servidor, siga estos pasos:

  1. En el archivo src/components/RestaurantListings.jsx , observe el siguiente código, que ya está escrito para usted:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

        return () => {
                unsubscribe();
        };
}, [filters]);

Este código invoca la función getRestaurantsSnapshot() , que es similar a la función getRestaurants() que implementó en un paso anterior. Sin embargo, esta función de instantánea proporciona un mecanismo de devolución de llamada para que la devolución de llamada se invoque cada vez que se realice un cambio en la colección del restaurante.

  1. En el archivo src/lib/firebase/firestore.js , reemplace la función getRestaurantsSnapshot() con el siguiente código:
export function getRestaurantsSnapshot(cb, filters = {}) {
        if (typeof cb !== "function") {
                console.log("Error: The callback parameter is not a function");
                return;
        }

        let q = query(collection(db, "restaurants"));
        q = applyQueryFilters(q, filters);

        const unsubscribe = onSnapshot(q, querySnapshot => {
                const results = querySnapshot.docs.map(doc => {
                        return {
                                id: doc.id,
                                ...doc.data(),
                                // Only plain objects can be passed to Client Components from Server Components
                                timestamp: doc.data().timestamp.toDate(),
                        };
                });

                cb(results);
        });

        return unsubscribe;
}

Los cambios realizados a través de la página de la base de datos de Firestore ahora se reflejan en la aplicación web en tiempo real.

  1. En la aplicación web, seleccione 27ca5d1e8ed8adfe.png > Agregar restaurantes de muestra . Si su función de instantánea se implementa correctamente, los restaurantes aparecen en tiempo real sin necesidad de actualizar la página.

8. Guarde los datos del usuario desde la aplicación web.

  1. En el archivo src/lib/firebase/firestore.js , reemplace la función updateWithRating() con el siguiente código:
const updateWithRating = async (
        transaction,
        docRef,
        newRatingDocument,
        review
) => {
        const restaurant = await transaction.get(docRef);
        const data = restaurant.data();
        const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
        const newSumRating = (data?.sumRating || 0) + Number(review.rating);
        const newAverage = newSumRating / newNumRatings;

        transaction.update(docRef, {
                numRatings: newNumRatings,
                sumRating: newSumRating,
                avgRating: newAverage,
        });

        transaction.set(newRatingDocument, {
                ...review,
                timestamp: Timestamp.fromDate(new Date()),
        });
};

Este código inserta un nuevo documento de Firestore que representa la nueva revisión. El código también actualiza el documento existente de Firestore que representa el restaurante con cifras actualizadas para el número de calificaciones y la calificación promedio calculada.

  1. Reemplace la función addReviewToRestaurant() con el siguiente código:
export async function addReviewToRestaurant(db, restaurantId, review) {
        if (!restaurantId) {
                throw new Error("No restaurant ID was provided.");
        }

        if (!review) {
                throw new Error("A valid review has not been provided.");
        }

        try {
                const docRef = doc(collection(db, "restaurants"), restaurantId);
                const newRatingDocument = doc(
                        collection(db, `restaurants/${restaurantId}/ratings`)
                );

                await runTransaction(db, transaction =>
                        updateWithRating(transaction, docRef, newRatingDocument, review)
                );
        } catch (error) {
                console.error(
                        "There was an error adding the rating to the restaurant.",
                        error
                );
                throw error;
        }
}

Implementar una acción del servidor Next.js

Una acción de servidor Next.js proporciona una API conveniente para acceder a los datos del formulario, como data.get("text") para obtener el valor del texto de la carga útil de envío del formulario.

Para utilizar una acción del servidor Next.js para procesar el envío del formulario de revisión, siga estos pasos:

  1. En el archivo src/components/ReviewDialog.jsx , busque el atributo action en el elemento <form> .
<form action={handleReviewFormSubmission}>

El valor del atributo action se refiere a una función que implementa en el siguiente paso.

  1. En el archivo src/app/actions.js , reemplace la función handleReviewFormSubmission() con el siguiente código:
// This is a next.js server action, which is an alpha feature, so
// use with caution.
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
export async function handleReviewFormSubmission(data) {
        const { app } = await getAuthenticatedAppForUser();
        const db = getFirestore(app);

        await addReviewToRestaurant(db, data.get("restaurantId"), {
                text: data.get("text"),
                rating: data.get("rating"),

                // This came from a hidden form field.
                userId: data.get("userId"),
        });
}

Agregar reseñas para un restaurante

Implementó soporte para envíos de reseñas, por lo que ahora puede verificar que sus reseñas se inserten correctamente en Cloud Firestore.

Para agregar una reseña y verificar que esté insertada en Cloud Firestore, sigue estos pasos:

  1. En la aplicación web, seleccione un restaurante desde la página de inicio.
  2. En la página del restaurante, haga clic en 3e19beef78bb0d0e.png .
  3. Seleccione una calificación de estrellas.
  4. Escribe una reseña.
  5. Haga clic en Enviar . Su reseña aparece en la parte superior de la lista de reseñas.
  6. En Cloud Firestore, busque en el panel Agregar documento el documento del restaurante que revisó y selecciónelo.
  7. En el panel Iniciar colección , seleccione calificaciones .
  8. En el panel Agregar documento , busque el documento que desea revisar para verificar que se haya insertado como se esperaba.

Documentos en el emulador de Firestore

9. Guarde los archivos cargados por el usuario desde la aplicación web.

En esta sección, agrega funcionalidad para poder reemplazar la imagen asociada con un restaurante cuando inicia sesión. Carga la imagen en Firebase Storage y actualiza la URL de la imagen en el documento de Cloud Firestore que representa el restaurante.

Para guardar archivos cargados por el usuario desde la aplicación web, siga estos pasos:

  1. En el archivo src/components/Restaurant.jsx , observe el código que se ejecuta cuando el usuario carga un archivo:
async function handleRestaurantImage(target) {
        const image = target.files ? target.files[0] : null;
        if (!image) {
                return;
        }

        const imageURL = await updateRestaurantImage(id, image);
        setRestaurant({ ...restaurant, photo: imageURL });
}

No se necesitan cambios, pero implementas el comportamiento de la función updateRestaurantImage() en los siguientes pasos.

  1. En el archivo src/lib/firebase/storage.js , reemplace las funciones updateRestaurantImage() y uploadImage() con el siguiente código:
export async function updateRestaurantImage(restaurantId, image) {
        try {
                if (!restaurantId)
                        throw new Error("No restaurant ID has been provided.");

                if (!image || !image.name)
                        throw new Error("A valid image has not been provided.");

                const publicImageUrl = await uploadImage(restaurantId, image);
                await updateRestaurantImageReference(restaurantId, publicImageUrl);

                return publicImageUrl;
        } catch (error) {
                console.error("Error processing request:", error);
        }
}

async function uploadImage(restaurantId, image) {
        const filePath = `images/${restaurantId}/${image.name}`;
        const newImageRef = ref(storage, filePath);
        await uploadBytesResumable(newImageRef, image);

        return await getDownloadURL(newImageRef);
}

La función updateRestaurantImageReference() ya está implementada para usted. Esta función actualiza un documento de restaurante existente en Cloud Firestore con una URL de imagen actualizada.

Verificar la funcionalidad de carga de imágenes

Para verificar que la imagen se cargue como se esperaba, siga estos pasos:

  1. En la aplicación web, verifique que haya iniciado sesión y seleccione un restaurante.
  2. Hacer clic 7067eb41fea41ff0.png y cargue una imagen desde su sistema de archivos. Su imagen sale de su entorno local y se carga en Cloud Storage. La imagen aparece inmediatamente después de cargarla.
  3. Navegue hasta Almacenamiento en la nube para Firebase.
  4. Navegue hasta la carpeta que representa el restaurante. La imagen que subiste existe en la carpeta.

6cf3f9e2303c931c.png

10. Conclusión

¡Felicidades! Aprendiste a usar Firebase para agregar características y funcionalidades a una aplicación Next.js. Específicamente, usaste lo siguiente:

Aprende más