Integra Firebase con un'app Next.js

1. Prima di iniziare

In questo codelab imparerai come integrare Firebase con un'app Web Next.js chiamata Friendly Eats, che è un sito Web per recensioni di ristoranti.

Applicazione web Friendly Eats

L'app Web completata offre funzionalità utili che dimostrano come Firebase può aiutarti a creare app Next.js. Queste funzionalità includono quanto segue:

  • Funzionalità di accesso con Google e disconnessione: l'app Web completata ti consente di accedere con Google e disconnetterti. L'accesso e la persistenza dell'utente sono gestiti interamente tramite l'autenticazione Firebase .
  • Immagini: l'app Web completata consente agli utenti che hanno effettuato l'accesso di caricare immagini di ristoranti. Le risorse immagine vengono archiviate in Cloud Storage for Firebase . L'SDK JavaScript di Firebase fornisce un URL pubblico per le immagini caricate. Questo URL pubblico viene quindi archiviato nel documento del ristorante pertinente in Cloud Firestore .
  • Recensioni: l'app Web completata consente agli utenti che hanno effettuato l'accesso di pubblicare recensioni di ristoranti costituite da una valutazione a stelle e da un messaggio di testo. Le informazioni sulle recensioni vengono archiviate in Cloud Firestore.
  • Filtri: l'app Web completata consente agli utenti che hanno effettuato l'accesso di filtrare l'elenco dei ristoranti in base alla categoria, alla posizione e al prezzo. È inoltre possibile personalizzare il metodo di ordinamento utilizzato. Si accede ai dati da Cloud Firestore e le query Firestore vengono applicate in base ai filtri utilizzati.

Prerequisiti

  • Conoscenza di Next.js e JavaScript

Cosa imparerai

  • Come utilizzare Firebase con il router dell'app Next.js e il rendering lato server.
  • Come rendere persistenti le immagini in Cloud Storage for Firebase.
  • Come leggere e scrivere dati in un database Cloud Firestore.
  • Come utilizzare l'accesso con Google con l'SDK JavaScript Firebase.

Di cosa avrai bisogno

  • Idiota
  • Il kit di sviluppo Java
  • Una recente versione stabile di Node.js
  • Un browser a tua scelta, come Google Chrome
  • Un ambiente di sviluppo con un editor di codice e un terminale
  • Un account Google per la creazione e la gestione del tuo progetto Firebase
  • La possibilità di aggiornare il tuo progetto Firebase al piano tariffario Blaze

2. Configura il tuo ambiente di sviluppo

Questo codelab fornisce la codebase iniziale dell'app e si basa sulla CLI Firebase.

Scarica l'archivio

  1. Nel tuo terminale, clona il repository GitHub del codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. Il repository GitHub contiene progetti di esempio per più piattaforme. Tuttavia, questo codelab utilizza solo la directory nextjs-start . Prendi nota delle seguenti directory:
    • nextjs-start : contiene il codice iniziale su cui costruisci.
    • nextjs-end : contiene il codice della soluzione per l'app Web completata.
  3. Nel tuo terminale, vai alla directory nextjs-start e installa le dipendenze necessarie:
    cd friendlyeats-web/nextjs-start
    npm install
    

Installa o aggiorna la CLI Firebase

Esegui il comando seguente per verificare di aver installato la CLI Firebase e che sia v12.5.4 o successiva:

firebase --version
  • Se hai installato la CLI Firebase, ma non è la versione 12.5.4 o successiva, aggiornala:
    npm update -g firebase-tools
    
  • Se non hai installato la CLI Firebase, installala:
    npm install -g firebase-tools
    

Se non riesci a installare la CLI Firebase a causa di errori di autorizzazione, consulta la documentazione di npm o utilizza un'altra opzione di installazione .

Accedi a Firebase

  1. Esegui il comando seguente per accedere alla CLI Firebase:
    firebase login
    
  2. A seconda che desideri che Firebase raccolga dati, inserisci Y o N .
  3. Nel browser, seleziona il tuo account Google, quindi fai clic su Consenti .

3. Configura il tuo progetto Firebase

In questa sezione configurerai un progetto Firebase e ti assocerai un'app Web Firebase. Configurarai anche i servizi Firebase utilizzati dall'app Web di esempio.

Crea un progetto Firebase

  1. Nella console Firebase , fai clic su Crea progetto .
  2. Nella casella di testo Inserisci il nome del tuo progetto , inserisci FriendlyEats Codelab (o un nome di progetto a tua scelta), quindi fai clic su Continua .
  3. Per questo codelab non è necessario Google Analytics, quindi disattiva l'opzione Abilita Google Analytics per questo progetto .
  4. Fare clic su Crea progetto .
  5. Attendi il provisioning del tuo progetto, quindi fai clic su Continua .
  6. Nel tuo progetto Firebase, vai a Impostazioni progetto . Annota l'ID del tuo progetto perché ti servirà in seguito. Questo identificatore univoco è il modo in cui viene identificato il tuo progetto (ad esempio, nella CLI Firebase).

Aggiungi un'app Web al tuo progetto Firebase

  1. Passa alla panoramica del progetto nel progetto Firebase, quindi fai clic su e41f2efdd9539c31.png Ragnatela .
  2. Nella casella di testo Soprannome dell'app , inserisci un soprannome dell'app facile da ricordare, ad esempio My Next.js app .
  3. Seleziona la casella di controllo Configura anche hosting Firebase per questa app .
  4. Fai clic su Registra app > Avanti > Avanti > Continua sulla console .

Aggiorna il tuo piano tariffario Firebase

Per utilizzare i framework web, il tuo progetto Firebase deve essere incluso nel piano tariffario Blaze , il che significa che è associato a un account di fatturazione Cloud .

  • Un account di fatturazione Cloud richiede un metodo di pagamento, ad esempio una carta di credito.
  • Se non hai mai utilizzato Firebase e Google Cloud, verifica se hai diritto a un credito di $ 300 e a un account di fatturazione Cloud di prova gratuita .

Tuttavia, tieni presente che il completamento di questo codelab non dovrebbe comportare alcun addebito effettivo.

Per aggiornare il tuo progetto al piano Blaze, segui questi passaggi:

  1. Nella console Firebase, seleziona per aggiornare il tuo piano .
  2. Nella finestra di dialogo, seleziona il piano Blaze, quindi segui le istruzioni visualizzate sullo schermo per associare il tuo progetto a un account di fatturazione Cloud.
    Se avessi bisogno di creare un account di fatturazione Cloud, potresti dover tornare al flusso di aggiornamento nella console Firebase per completare l'aggiornamento.

Configura i servizi Firebase nella console Firebase

Configura l'autenticazione

  1. Nella console Firebase, vai a Authentication .
  2. Fare clic su Inizia .
  3. Nella colonna Fornitori aggiuntivi , fai clic su Google > Abilita .
  4. Nella casella di testo Nome pubblico per il progetto , inserisci un nome facile da ricordare, ad esempio My Next.js app .
  5. Dal menu a discesa E-mail di supporto per il progetto , seleziona il tuo indirizzo e-mail.
  6. Fare clic su Salva .

Configura Cloud Firestore

  1. Nella console Firebase, vai a Firestore .
  2. Fare clic su Crea database > Avvia in modalità test > Avanti .
    Più avanti in questo codelab aggiungerai le regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo database .
  3. Utilizza la posizione predefinita o seleziona una posizione a tua scelta.
    Per un'app reale, vuoi scegliere una posizione vicina ai tuoi utenti. Tieni presente che questa posizione non può essere modificata in seguito e sarà automaticamente anche la posizione del tuo bucket Cloud Storage predefinito (passaggio successivo).
  4. Fare clic su Fine .

Configura Cloud Storage per Firebase

  1. Nella console Firebase, vai a Archiviazione .
  2. Fare clic su Inizia > Avvia in modalità test > Avanti .
    Più avanti in questo codelab aggiungerai le regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo bucket di archiviazione .
  3. La posizione del tuo bucket dovrebbe già essere selezionata (a causa della configurazione di Firestore nel passaggio precedente).
  4. Fare clic su Fine .

4. Esaminare la codebase iniziale

In questa sezione esaminerai alcune aree del codebase iniziale dell'app a cui aggiungerai funzionalità in questo codelab.

Struttura di cartelle e file

La tabella seguente contiene una panoramica della struttura delle cartelle e dei file dell'app:

Cartelle e file

Descrizione

src/components

Componenti React per filtri, intestazioni, dettagli del ristorante e recensioni

src/lib

Funzioni di utilità che non sono necessariamente legate a React o Next.js

src/lib/firebase

Codice specifico di Firebase e configurazione di Firebase

public

Risorse statiche nell'app Web, come le icone

src/app

Routing con il router dell'app Next.js

src/app/restaurant

Un gestore di route API

package.json e package-lock.json

Dipendenze del progetto con npm

next.config.js

Configurazione specifica di Next.js (le azioni del server sono abilitate )

jsconfig.json

Configurazione del servizio linguistico JavaScript

Componenti server e client

L'app è un'app Web Next.js che utilizza App Router . Il rendering del server viene utilizzato in tutta l'app. Ad esempio, il file src/app/page.js è un componente server responsabile della pagina principale. Il file src/components/RestaurantListings.jsx è un componente client indicato dalla direttiva "use client" all'inizio del file.

Importa dichiarazioni

Potresti notare istruzioni di importazione come le seguenti:

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

L'app utilizza il simbolo @ per evitare scomodi percorsi di importazione relativi ed è resa possibile dagli alias di percorso .

API specifiche di Firebase

Tutto il codice API Firebase è racchiuso nella directory src/lib/firebase . I singoli componenti React importano quindi le funzioni racchiuse dalla directory src/lib/firebase , anziché importare direttamente le funzioni Firebase.

Dati fittizi

I dati dei ristoranti e delle recensioni fittizie sono contenuti nel file src/lib/randomData.js . I dati di quel file vengono assemblati nel codice nel file src/lib/fakeRestaurants.js .

5. Configura l'hosting locale con l'emulatore Firebase Hosting

In questa sezione utilizzerai l' emulatore Firebase Hosting per eseguire l'app Web Next.js localmente.

Alla fine di questa sezione, l'emulatore Firebase Hosting esegue l'app Next.js per te, quindi non è necessario eseguire Next.js in un processo separato dagli emulatori.

Scarica e utilizza un account di servizio Firebase

L'app Web che creerai in questo codelab utilizza il rendering lato server con Next.js .

Firebase Admin SDK per Node.js viene utilizzato per garantire che le regole di sicurezza funzionino dal codice lato server. Per utilizzare le API in Firebase Admin, devi scaricare e utilizzare un account di servizio Firebase dalla console Firebase.

  1. Nella console Firebase, vai alla pagina Account di servizio nelle Impostazioni del progetto .
  2. Fare clic su Genera nuova chiave privata > Genera chiave .
  3. Dopo che il file è stato scaricato sul tuo file system, ottieni il percorso completo di quel file.
    Ad esempio, se hai scaricato il file nella directory Download , il percorso completo potrebbe essere simile a questo: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. Nel tuo terminale, imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS sul percorso della chiave privata scaricata. In un ambiente Unix, il comando potrebbe assomigliare a questo:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Mantieni questo terminale aperto e utilizzalo per il resto del codelab, poiché la variabile di ambiente potrebbe andare persa se avvii una nuova sessione di terminale.
    Se apri una nuova sessione del terminale, devi eseguire nuovamente il comando precedente.

Aggiungi la configurazione Firebase al codice dell'app Web

  1. Nella console Firebase, vai alle Impostazioni progetto .
  2. Nel riquadro di installazione e configurazione dell'SDK , trova la variabile firebaseConfig e copia le sue proprietà e i relativi valori.
  3. Apri il file .env nel tuo editor di codice e inserisci i valori delle variabili di ambiente con i valori di configurazione dalla console Firebase.
  4. Nel file sostituisci le proprietà esistenti con quelle che hai copiato.
  5. Salvare il file.

Inizializza l'app Web con il tuo progetto Firebase

Per connettere l'app Web al tuo progetto Firebase, procedi nel seguente modo:

  1. Nel tuo terminale, assicurati che i framework web siano abilitati in Firebase:
    firebase experiments:enable webframeworks
    
  2. Inizializza Firebase:
    firebase init
    
  3. Seleziona le seguenti opzioni:
    • Firestore: configura le regole di sicurezza e indicizza i file per Firestore
    • Hosting: configura i file per Firebase Hosting e (facoltativo) configura le distribuzioni di GitHub Action
    • Archiviazione: configura un file di regole di sicurezza per Cloud Storage
    • Emulatori: configura emulatori locali per i prodotti Firebase
  4. Seleziona Utilizza un progetto esistente e quindi inserisci l'ID progetto annotato in precedenza.
  5. Seleziona i valori predefiniti per tutte le domande successive fino a raggiungere la domanda In quale regione desideri ospitare il contenuto lato server, se applicabile? . Il terminale visualizza un messaggio che rileva una codebase Next.js esistente nella directory corrente.
  6. Per la domanda In quale regione desideri ospitare il contenuto lato server, se applicabile? , seleziona la posizione selezionata in precedenza per Firestore e Cloud Storage.
  7. Seleziona i valori predefiniti per tutte le domande successive fino a raggiungere la domanda Quali emulatori Firebase vuoi configurare? . Per questa domanda, seleziona Emulatore di funzioni e Emulatore di hosting .
  8. Seleziona i valori predefiniti per tutte le altre domande.

Distribuire le regole di sicurezza

Il codice contiene già una serie di regole di sicurezza per Firestore e per Cloud Storage per Firebase. Dopo aver distribuito le regole di sicurezza, i dati nel tuo database e nel tuo bucket sono meglio protetti da usi impropri.

  1. Per implementare queste regole di sicurezza, esegui questo comando nel tuo terminale:
    firebase deploy --only firestore:rules,storage
    
  2. Se ti viene chiesto: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" , seleziona .

Avvia l'emulatore di hosting

  1. Nel tuo terminale, avvia l'emulatore di Hosting:
    firebase emulators:start --only hosting
    
    Il tuo terminale risponde con la porta dove puoi trovare l'emulatore di Hosting, ad esempio http://localhost:5000/ .

Terminale che mostra che l'emulatore di hosting è pronto

  1. Nel tuo browser, vai all'URL con l'emulatore Firebase Hosting.
  2. Se vedi l'errore nella pagina web che inizia in questo modo: "Error: Firebase session cookie has incorrect..." , devi eliminare tutti i cookie nel tuo ambiente host locale. Per fare ciò, seguire le istruzioni in eliminare i cookie | Documentazione di DevTools .

Un errore di sessione del cookie

Eliminazione dei cookie in DevTools

Ora puoi vedere la web app iniziale! Anche se stai visualizzando l'app Web su un URL host locale, utilizza i servizi Firebase reali che hai configurato nella tua console.

6. Aggiungi l'autenticazione all'app Web

In questa sezione aggiungi l'autenticazione all'app Web in modo da poterti accedere.

Implementare le funzioni di accesso e disconnessione

  1. Nel file src/lib/firebase/auth.js , sostituisci le funzioni onAuthStateChanged , signInWithGoogle e signOut con il seguente codice:
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);
        }
}

Questo codice utilizza le seguenti API Firebase:

API Firebase

Descrizione

GoogleAuthProvider

Crea un'istanza del provider di autenticazione Google.

signInWithPopup

Avvia un flusso di autenticazione basato su finestre di dialogo.

auth.signOut

Disconnette l'utente.

Nel file src/components/Header.jsx , il codice richiama già le funzioni signInWithGoogle e signOut .

  1. Nell'app Web, aggiorna la pagina e fai clic su Accedi con Google . L'app Web non si aggiorna, quindi non è chiaro se l'accesso è riuscito.

Sottoscrivi le modifiche all'autenticazione

Per sottoscrivere le modifiche all'autenticazione, attenersi alla seguente procedura:

  1. Passare al file src/components/Header.jsx .
  2. Sostituisci la funzione useUserSession con il seguente codice:
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;
}

Questo codice utilizza un hook dello stato React per aggiornare l'utente quando la funzione onAuthStateChanged specifica che c'è una modifica allo stato di autenticazione.

Verificare le modifiche

Il layout root nel file src/app/layout.js esegue il rendering dell'intestazione e passa l'utente, se disponibile, come oggetto di scena.

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

Ciò significa che il componente <Header> esegue il rendering dei dati utente, se disponibili, durante il runtime del server. Se sono presenti aggiornamenti di autenticazione durante il ciclo di vita della pagina dopo il caricamento iniziale della pagina, il gestore onAuthStateChanged li gestisce.

Ora è il momento di testare l'app Web e verificare ciò che hai creato.

Per verificare il nuovo comportamento di autenticazione, attenersi alla seguente procedura:

  1. Nel browser, aggiorna l'app Web. Il tuo nome visualizzato viene visualizzato nell'intestazione.
  2. Esci e accedi di nuovo. La pagina si aggiorna in tempo reale senza un aggiornamento della pagina. Puoi ripetere questo passaggio con utenti diversi.
  3. Facoltativo: fare clic con il pulsante destro del mouse sull'app Web, selezionare Visualizza origine pagina e cercare il nome visualizzato. Appare nel sorgente HTML non elaborato restituito dal server.

7. Visualizza le informazioni sul ristorante

L'app Web include dati fittizi per ristoranti e recensioni.

Aggiungi uno o più ristoranti

Per inserire dati simulati sui ristoranti nel database Cloud Firestore locale, procedi nel seguente modo:

  1. Nell'app Web selezionare 2cf67d488d8e6332.png > Aggiungi ristoranti campione .
  2. Nella console Firebase nella pagina Database Firestore , seleziona ristoranti . Vengono visualizzati i documenti di livello superiore nella raccolta ristoranti, ognuno dei quali rappresenta un ristorante.
  3. Fai clic su alcuni documenti per esplorare le proprietà di un documento di ristorante.

Visualizza l'elenco dei ristoranti

Il tuo database Cloud Firestore ora dispone di ristoranti che l'app Web Next.js può visualizzare.

Per definire il codice di recupero dei dati, attenersi alla seguente procedura:

  1. Nel file src/app/page.js , trova il componente server <Home /> ed esamina la chiamata alla funzione getRestaurants , che recupera un elenco di ristoranti in fase di esecuzione del server. Implementerai la funzione getRestaurants nei passaggi seguenti.
  2. Nel file src/lib/firebase/firestore.js , sostituisci le funzioni applyQueryFilters e getRestaurants con il seguente codice:
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. Aggiorna l'app Web. Le immagini dei ristoranti vengono visualizzate come riquadri nella pagina.

Verifica che gli elenchi dei ristoranti vengano caricati durante l'esecuzione del server

Utilizzando il framework Next.js, potrebbe non essere ovvio quando i dati vengono caricati in fase di esecuzione del server o in fase di esecuzione lato client.

Per verificare che gli elenchi dei ristoranti vengano caricati durante l'esecuzione del server, attenersi alla seguente procedura:

  1. Nell'app Web, apri DevTools e disabilita JavaScript .

Disabilita JavaScipt in DevTools

  1. Aggiorna l'app Web. Gli elenchi dei ristoranti vengono ancora caricati. Le informazioni sul ristorante vengono restituite nella risposta del server. Quando JavaScript è abilitato, le informazioni sul ristorante vengono idratate tramite il codice JavaScript lato client.
  2. In DevTools, riattiva JavaScript .

Ascolta gli aggiornamenti sui ristoranti con gli ascoltatori di snapshot di Cloud Firestore

Nella sezione precedente, hai visto come viene caricato il set iniziale di ristoranti dal file src/app/page.js . Il file src/app/page.js è un componente server e viene visualizzato sul server, incluso il codice di recupero dati Firebase.

Il file src/components/RestaurantListings.jsx è un componente client e può essere configurato per idratare il markup rappresentato dal server.

Per configurare il file src/components/RestaurantListings.jsx per idratare il markup renderizzato dal server, attenersi alla seguente procedura:

  1. Nel file src/components/RestaurantListings.jsx , osserva il seguente codice, che è già scritto per te:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

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

Questo codice richiama la funzione getRestaurantsSnapshot() , che è simile alla funzione getRestaurants() implementata in un passaggio precedente. Tuttavia, questa funzione di istantanea fornisce un meccanismo di richiamata in modo che la richiamata venga richiamata ogni volta che viene apportata una modifica alla collezione del ristorante.

  1. Nel file src/lib/firebase/firestore.js , sostituisci la funzione getRestaurantsSnapshot() con il seguente codice:
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;
}

Le modifiche apportate tramite la pagina del database Firestore ora si riflettono nell'app Web in tempo reale.

  1. Nell'app Web selezionare 27ca5d1e8ed8adfe.png > Aggiungi ristoranti campione . Se la funzione snapshot è implementata correttamente, i ristoranti verranno visualizzati in tempo reale senza aggiornare la pagina.

8. Salva i dati utente dall'app Web

  1. Nel file src/lib/firebase/firestore.js , sostituisci la funzione updateWithRating() con il seguente codice:
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()),
        });
};

Questo codice inserisce un nuovo documento Firestore che rappresenta la nuova revisione. Il codice aggiorna anche il documento Firestore esistente che rappresenta il ristorante con dati aggiornati relativi al numero di valutazioni e alla valutazione media calcolata.

  1. Sostituisci la funzione addReviewToRestaurant() con il seguente codice:
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;
        }
}

Implementa un'azione server Next.js

Un'azione server Next.js fornisce un'API pratica per accedere ai dati del modulo, ad esempio data.get("text") per ottenere il valore del testo dal payload di invio del modulo.

Per utilizzare un'azione server Next.js per elaborare l'invio del modulo di revisione, attenersi alla seguente procedura:

  1. Nel file src/components/ReviewDialog.jsx , trova l'attributo action nell'elemento <form> .
<form action={handleReviewFormSubmission}>

Il valore dell'attributo action si riferisce a una funzione che implementerai nel passaggio successivo.

  1. Nel file src/app/actions.js , sostituisci la funzione handleReviewFormSubmission() con il seguente codice:
// 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"),
        });
}

Aggiungi recensioni per un ristorante

Hai implementato il supporto per l'invio delle recensioni, quindi ora puoi verificare che le tue recensioni siano inserite correttamente in Cloud Firestore.

Per aggiungere una recensione e verificare che sia inserita in Cloud Firestore, procedi nel seguente modo:

  1. Nell'app Web, seleziona un ristorante dalla home page.
  2. Nella pagina del ristorante, fare clic su 3e19beef78bb0d0e.png .
  3. Seleziona una valutazione in stelle.
  4. Scrivere una recensione.
  5. Fare clic su Invia . La tua recensione viene visualizzata in cima all'elenco delle recensioni.
  6. In Cloud Firestore, cerca nel riquadro Aggiungi documento il documento del ristorante che hai esaminato e selezionalo.
  7. Nel riquadro Raccolta iniziale , seleziona valutazioni .
  8. Nel riquadro Aggiungi documento , trova il documento per la tua revisione per verificare che sia stato inserito come previsto.

Documenti nell'emulatore Firestore

9. Salva i file caricati dall'utente dall'app Web

In questa sezione aggiungi funzionalità in modo da poter sostituire l'immagine associata a un ristorante quando hai effettuato l'accesso. Carichi l'immagine su Firebase Storage e aggiorni l'URL dell'immagine nel documento Cloud Firestore che rappresenta il ristorante.

Per salvare i file caricati dall'utente dall'app Web, attenersi alla seguente procedura:

  1. Nel file src/components/Restaurant.jsx , osserva il codice che viene eseguito quando l'utente carica un file:
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 });
}

Non sono necessarie modifiche, ma implementi il ​​comportamento della funzione updateRestaurantImage() nei passaggi seguenti.

  1. Nel file src/lib/firebase/storage.js , sostituisci le funzioni updateRestaurantImage() e uploadImage() con il seguente codice:
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 funzione updateRestaurantImageReference() è già implementata per te. Questa funzione aggiorna un documento di ristorante esistente in Cloud Firestore con un URL di immagine aggiornato.

Verifica la funzionalità di caricamento delle immagini

Per verificare che l'immagine venga caricata come previsto, procedi nel seguente modo:

  1. Nell'app Web, verifica di aver effettuato l'accesso e seleziona un ristorante.
  2. Clic 7067eb41fea41ff0.png e carica un'immagine dal tuo filesystem. La tua immagine lascia il tuo ambiente locale e viene caricata su Cloud Storage. L'immagine appare immediatamente dopo averla caricata.
  3. Passare a Cloud Storage per Firebase.
  4. Passare alla cartella che rappresenta il ristorante. L'immagine che hai caricato esiste nella cartella.

6cf3f9e2303c931c.png

10. Conclusione

Congratulazioni! Hai imparato come utilizzare Firebase per aggiungere caratteristiche e funzionalità a un'app Next.js. Nello specifico, hai utilizzato quanto segue:

Saperne di più

,

1. Prima di iniziare

In questo codelab imparerai come integrare Firebase con un'app Web Next.js chiamata Friendly Eats, che è un sito Web per recensioni di ristoranti.

Applicazione web Friendly Eats

L'app Web completata offre funzionalità utili che dimostrano come Firebase può aiutarti a creare app Next.js. Queste funzionalità includono quanto segue:

  • Funzionalità di accesso con Google e disconnessione: l'app Web completata ti consente di accedere con Google e disconnetterti. L'accesso e la persistenza dell'utente sono gestiti interamente tramite l'autenticazione Firebase .
  • Immagini: l'app Web completata consente agli utenti che hanno effettuato l'accesso di caricare immagini di ristoranti. Le risorse immagine vengono archiviate in Cloud Storage for Firebase . L'SDK JavaScript di Firebase fornisce un URL pubblico per le immagini caricate. Questo URL pubblico viene quindi archiviato nel documento del ristorante pertinente in Cloud Firestore .
  • Recensioni: l'app Web completata consente agli utenti che hanno effettuato l'accesso di pubblicare recensioni di ristoranti costituite da una valutazione a stelle e da un messaggio di testo. Le informazioni sulle recensioni vengono archiviate in Cloud Firestore.
  • Filtri: l'app Web completata consente agli utenti che hanno effettuato l'accesso di filtrare l'elenco dei ristoranti in base alla categoria, alla posizione e al prezzo. È inoltre possibile personalizzare il metodo di ordinamento utilizzato. Si accede ai dati da Cloud Firestore e le query Firestore vengono applicate in base ai filtri utilizzati.

Prerequisiti

  • Conoscenza di Next.js e JavaScript

Cosa imparerai

  • Come utilizzare Firebase con il router dell'app Next.js e il rendering lato server.
  • Come rendere persistenti le immagini in Cloud Storage for Firebase.
  • Come leggere e scrivere dati in un database Cloud Firestore.
  • Come utilizzare l'accesso con Google con l'SDK JavaScript Firebase.

Di cosa avrai bisogno

  • Idiota
  • Il kit di sviluppo Java
  • Una recente versione stabile di Node.js
  • Un browser a tua scelta, come Google Chrome
  • Un ambiente di sviluppo con un editor di codice e un terminale
  • Un account Google per la creazione e la gestione del tuo progetto Firebase
  • La possibilità di aggiornare il tuo progetto Firebase al piano tariffario Blaze

2. Configura il tuo ambiente di sviluppo

Questo codelab fornisce la codebase iniziale dell'app e si basa sulla CLI Firebase.

Scarica l'archivio

  1. Nel tuo terminale, clona il repository GitHub del codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. Il repository GitHub contiene progetti di esempio per più piattaforme. Tuttavia, questo codelab utilizza solo la directory nextjs-start . Prendi nota delle seguenti directory:
    • nextjs-start : contiene il codice iniziale su cui costruisci.
    • nextjs-end : contiene il codice della soluzione per l'app Web completata.
  3. Nel tuo terminale, vai alla directory nextjs-start e installa le dipendenze necessarie:
    cd friendlyeats-web/nextjs-start
    npm install
    

Installa o aggiorna la CLI Firebase

Esegui il comando seguente per verificare di aver installato la CLI Firebase e che sia v12.5.4 o successiva:

firebase --version
  • Se hai installato la CLI Firebase, ma non è la versione 12.5.4 o successiva, aggiornala:
    npm update -g firebase-tools
    
  • Se non hai installato la CLI Firebase, installala:
    npm install -g firebase-tools
    

Se non riesci a installare la CLI Firebase a causa di errori di autorizzazione, consulta la documentazione di npm o utilizza un'altra opzione di installazione .

Accedi a Firebase

  1. Esegui il comando seguente per accedere alla CLI Firebase:
    firebase login
    
  2. A seconda che desideri che Firebase raccolga dati, inserisci Y o N .
  3. Nel browser, seleziona il tuo account Google, quindi fai clic su Consenti .

3. Configura il tuo progetto Firebase

In questa sezione configurerai un progetto Firebase e ti assocerai un'app Web Firebase. Configurarai anche i servizi Firebase utilizzati dall'app Web di esempio.

Crea un progetto Firebase

  1. Nella console Firebase , fai clic su Crea progetto .
  2. Nella casella di testo Inserisci il nome del tuo progetto , inserisci FriendlyEats Codelab (o un nome di progetto a tua scelta), quindi fai clic su Continua .
  3. Per questo codelab non è necessario Google Analytics, quindi disattiva l'opzione Abilita Google Analytics per questo progetto .
  4. Fare clic su Crea progetto .
  5. Attendi il provisioning del tuo progetto, quindi fai clic su Continua .
  6. Nel tuo progetto Firebase, vai a Impostazioni progetto . Annota l'ID del tuo progetto perché ti servirà in seguito. Questo identificatore univoco è il modo in cui viene identificato il tuo progetto (ad esempio, nella CLI Firebase).

Aggiungi un'app Web al tuo progetto Firebase

  1. Passa alla panoramica del progetto nel progetto Firebase, quindi fai clic su e41f2efdd9539c31.png Ragnatela .
  2. Nella casella di testo Soprannome dell'app , inserisci un soprannome dell'app facile da ricordare, ad esempio My Next.js app .
  3. Seleziona la casella di controllo Configura anche hosting Firebase per questa app .
  4. Fai clic su Registra app > Avanti > Avanti > Continua sulla console .

Aggiorna il tuo piano tariffario Firebase

Per utilizzare i framework web, il tuo progetto Firebase deve essere incluso nel piano tariffario Blaze , il che significa che è associato a un account di fatturazione Cloud .

  • Un account di fatturazione Cloud richiede un metodo di pagamento, ad esempio una carta di credito.
  • Se non hai mai utilizzato Firebase e Google Cloud, verifica se hai diritto a un credito di $ 300 e a un account di fatturazione Cloud di prova gratuita .

Tuttavia, tieni presente che il completamento di questo codelab non dovrebbe comportare alcun addebito effettivo.

Per aggiornare il tuo progetto al piano Blaze, segui questi passaggi:

  1. Nella console Firebase, seleziona per aggiornare il tuo piano .
  2. Nella finestra di dialogo, seleziona il piano Blaze, quindi segui le istruzioni visualizzate sullo schermo per associare il tuo progetto a un account di fatturazione Cloud.
    Se avessi bisogno di creare un account di fatturazione Cloud, potresti dover tornare al flusso di aggiornamento nella console Firebase per completare l'aggiornamento.

Configura i servizi Firebase nella console Firebase

Configura l'autenticazione

  1. Nella console Firebase, vai a Authentication .
  2. Fare clic su Inizia .
  3. Nella colonna Fornitori aggiuntivi , fai clic su Google > Abilita .
  4. Nella casella di testo Nome pubblico per il progetto , inserisci un nome facile da ricordare, ad esempio My Next.js app .
  5. Dal menu a discesa E-mail di supporto per il progetto , seleziona il tuo indirizzo e-mail.
  6. Fare clic su Salva .

Configura Cloud Firestore

  1. Nella console Firebase, vai a Firestore .
  2. Fare clic su Crea database > Avvia in modalità test > Avanti .
    Più avanti in questo codelab aggiungerai le regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo database .
  3. Utilizza la posizione predefinita o seleziona una posizione a tua scelta.
    Per un'app reale, vuoi scegliere una posizione vicina ai tuoi utenti. Tieni presente che questa posizione non può essere modificata in seguito e sarà automaticamente anche la posizione del tuo bucket Cloud Storage predefinito (passaggio successivo).
  4. Fare clic su Fine .

Configura Cloud Storage per Firebase

  1. Nella console Firebase, vai a Archiviazione .
  2. Fare clic su Inizia > Avvia in modalità test > Avanti .
    Più avanti in questo codelab aggiungerai le regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo bucket di archiviazione .
  3. La posizione del tuo bucket dovrebbe essere già selezionata (a causa della configurazione di Firestore nel passaggio precedente).
  4. Fare clic su Fine .

4. Esaminare la codebase iniziale

In questa sezione, esaminerai alcune aree della base di codice di avviamento dell'app a cui aggiungerai funzionalità in questo codelab.

Cartella e struttura dei file

La tabella seguente contiene una panoramica della cartella e della struttura dei file dell'app:

Cartelle e file

Descrizione

src/components

React componenti per filtri, intestazioni, dettagli sul ristorante e recensioni

src/lib

Funzioni di utilità che non sono necessariamente legate a reagire o successive.js

src/lib/firebase

Codice specifico per Firebase e configurazione Firebase

public

Risorse statiche nell'app web, come icone

src/app

Routing con il router dell'app Next.js

src/app/restaurant

Un gestore del percorso API

package.json e package-lock.json

Dipendenze del progetto con NPM

next.config.js

Configurazione specifica per JS. JS (le azioni del server sono abilitate )

jsconfig.json

Configurazione del servizio linguistico JavaScript

Componenti server e client

L'app è un'app Web Next.js che utilizza il router dell'app . Il rendering del server viene utilizzato in tutta l'app. Ad esempio, il file src/app/page.js è un componente server responsabile della pagina principale. Il file src/components/RestaurantListings.jsx è un componente client indicato dalla direttiva "use client" all'inizio del file.

Dichiarazioni di importazione

Potresti notare dichiarazioni di importazione come le seguenti:

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

L'app utilizza il simbolo @ per evitare percorsi di importazione relativi goffi ed è resa possibile dagli alias del percorso .

API specifiche per Firebase

Tutto il codice API Firebase è avvolto nella directory src/lib/firebase . I singoli componenti di reazione importano quindi le funzioni avvolte dalla directory src/lib/firebase , anziché importare direttamente le funzioni di Firebase.

Dati finti

I dati del ristorante e della revisione finti sono contenuti nel file src/lib/randomData.js . I dati di quel file sono assemblati nel codice nel file src/lib/fakeRestaurants.js .

5. Imposta hosting locale con l'emulatore di hosting Firebase

In questa sezione, utilizzerai l' emulatore di hosting Firebase per eseguire l'app Web Next.js a livello locale.

Entro la fine di questa sezione, l'emulatore di hosting Firebase esegue l'app Next.js per te, quindi non è necessario eseguire successivi.js in un processo separato per gli emulatori.

Scarica e utilizza un account di servizio Firebase

L'app Web che creerai in questo codelab utilizza il rendering lato server con Next.js.

Il Firebase Admin SDK per node.js viene utilizzato per garantire che le regole di sicurezza siano funzionali dal codice lato server. Per utilizzare le API in Firebase Admin, è necessario scaricare e utilizzare un account di servizio Firebase dalla console Firebase.

  1. Nella console Firebase, vai alla pagina degli account di servizio nelle impostazioni del progetto .
  2. Fare clic su Genera nuova chiave privata > Genera chiave .
  3. Dopo che il file è stato scaricato sul tuo filesystem, ottenere il percorso completo di quel file.
    Ad esempio, se hai scaricato il file nella directory dei download , il percorso completo potrebbe apparire così: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. Nel tuo terminale, imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS sul percorso della chiave privata scaricata. In un ambiente unix, il comando potrebbe apparire così:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Tieni questo terminale aperto e usalo per il resto di questo codelab, poiché la variabile di ambiente potrebbe essere persa se si avvia una nuova sessione di terminale.
    Se si apri una nuova sessione del terminale, è necessario eseguire il riemetro del comando precedente.

Aggiungi la tua configurazione Firebase al codice dell'app Web

  1. Nella console Firebase, vai alle impostazioni del progetto .
  2. Nel riquadro di configurazione e configurazione SDK , trova la variabile firebaseConfig e copia le sue proprietà e i loro valori.
  3. Apri il file .env nell'editor di codice e compila i valori della variabile di ambiente con i valori di configurazione dalla console Firebase.
  4. Nel file, sostituire le proprietà esistenti con quelle che hai copiato.
  5. Salva il file.

Inizializza l'app Web con il tuo progetto Firebase

Per collegare l'app Web al progetto Firebase, segui questi passaggi:

  1. Nel tuo terminale, assicurarsi che i quadri Web siano abilitati in Firebase:
    firebase experiments:enable webframeworks
    
  2. Inizializza Firebase:
    firebase init
    
  3. Seleziona le seguenti opzioni:
    • Firestore: configurare regole di sicurezza e indicizza i file per Firestore
    • Hosting: configurare i file per hosting Firebase e (facoltativamente) impostare l'azione Github
    • Archiviazione: configurare un file di regole di sicurezza per l'archiviazione cloud
    • Emulatori: istituire emulatori locali per i prodotti Firebase
  4. Seleziona Utilizzare un progetto esistente , quindi immettere l'ID progetto che hai precedentemente notato.
  5. Selezionare i valori predefiniti per tutte le domande successive fino a raggiungere la domanda in quale regione desideri ospitare il contenuto sul lato server, se applicabile? . Il terminale visualizza un messaggio che rileva una base di codice Next.js esistente nella directory corrente.
  6. Per la domanda in quale regione desideri ospitare il contenuto sul lato server, se applicabile? , Seleziona la posizione che hai precedentemente selezionato per FireStore e Cloud Storage.
  7. Selezionare i valori predefiniti per tutte le domande successive fino a raggiungere la domanda quali emulatori di Firebase vuoi impostare? . Per questa domanda, seleziona Emulatore delle funzioni e emulatore di hosting .
  8. Seleziona i valori predefiniti per tutte le altre domande.

Distribuire regole di sicurezza

Il codice ha già set di regole di sicurezza per FireStore e per l'archiviazione del cloud per Firebase. Dopo aver distribuito le regole di sicurezza, i dati nel tuo database e il bucket sono meglio protetti dall'uso improprio.

  1. Per distribuire queste regole di sicurezza, eseguire questo comando nel tuo terminale:
    firebase deploy --only firestore:rules,storage
    
  2. Se ti viene chiesto: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" , seleziona .

Avvia l'emulatore di hosting

  1. Nel tuo terminale, avvia l'emulatore di hosting:
    firebase emulators:start --only hosting
    
    Il tuo terminale risponde con la porta in cui è possibile trovare l'emulatore di hosting, ad esempio http: // localhost: 5000/ .

Terminale che mostra che l'emulatore di hosting è pronto

  1. Nel tuo browser, vai all'URL con l'emulatore di hosting Firebase.
  2. Se vedi l'errore nella pagina Web che inizia in questo modo: "Error: Firebase session cookie has incorrect..." , è necessario eliminare tutti i cookie nel tuo ambiente locale. Per fare ciò, seguire le istruzioni in Elimina i cookie | Documentazione DevTools .

Un errore di sessione di cookie

Eliminazione dei biscotti in DevTools

Ora puoi vedere l'app Web iniziale! Anche se stai visualizzando l'app Web su un URL LocalHost, utilizza i servizi Firebase reali che hai configurato nella tua console.

6. Aggiungi autenticazione all'app Web

In questa sezione, aggiungi autenticazione all'app Web in modo da poter accedervi.

Implementa le funzioni di accesso e firma

  1. Nel file src/lib/firebase/auth.js , sostituire le funzioni onAuthStateChanged , signInWithGoogle e signOut con il seguente codice:
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);
        }
}

Questo codice utilizza le seguenti API Firebase:

API Firebase

Descrizione

GoogleAuthProvider

Crea un'istanza del provider di autenticazione di Google.

signInWithPopup

Avvia un flusso di autenticazione basato sulla finestra di dialogo.

auth.signOut

Firma l'utente.

Nel file src/components/Header.jsx , il codice invoca già le funzioni signInWithGoogle e signOut .

  1. Nell'app Web, aggiorna la pagina e fai clic su Accedi con Google . L'app Web non si aggiorna, quindi non è chiaro se l'accesso sia riuscito.

Iscriviti alle modifiche all'autenticazione

Per iscriverti alle modifiche all'autenticazione, seguire questi passaggi:

  1. Passare al file src/components/Header.jsx .
  2. Sostituire la funzione useUserSession con il seguente codice:
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;
}

Questo codice utilizza un gancio di stato di react per aggiornare l'utente quando la funzione onAuthStateChanged specifica che c'è una modifica allo stato di autenticazione.

Verificare le modifiche

Il layout root nel file src/app/layout.js rende l'intestazione e passa nell'utente, se disponibile, come prop.

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

Ciò significa che il componente <Header> rende i dati utente, se disponibili, durante il tempo di esecuzione del server. Se ci sono aggiornamenti di autenticazione durante il ciclo di vita della pagina dopo il caricamento della pagina iniziale, il gestore onAuthStateChanged li gestisce.

Ora è il momento di testare l'app Web e verificare ciò che hai creato.

Per verificare il nuovo comportamento di autenticazione, seguire questi passaggi:

  1. Nel tuo browser, aggiorna l'app Web. Il tuo nome visualizzato appare nell'intestazione.
  2. Accedere e accedere di nuovo. La pagina si aggiorna in tempo reale senza un aggiornamento della pagina. Puoi ripetere questo passaggio con utenti diversi.
  3. Opzionale: fare clic con il tasto destro sull'app Web, selezionare l'origine della pagina Visualizza e cercare il nome di visualizzazione. Appare nell'origine HTML RAW restituita dal server.

7. Visualizza le informazioni sul ristorante

L'app Web include dati finti per ristoranti e recensioni.

Aggiungi uno o più ristoranti

Per inserire i dati del ristorante finto nel database Cloud FireStore locale, segui questi passaggi:

  1. Nell'app Web, seleziona 2cf67d488d8e6332.png > Aggiungi ristoranti campione .
  2. Nella console Firebase nella pagina del database FireStore , selezionare ristoranti . Vedi i documenti di alto livello nella collezione di ristoranti, ognuno dei quali rappresenta un ristorante.
  3. Fai clic su alcuni documenti per esplorare le proprietà di un documento di ristorante.

Visualizza l'elenco dei ristoranti

Il tuo database Cloud FireStore ora ha ristoranti che l'app Web Next.js può visualizzare.

Per definire il codice di cattura dei dati, seguire questi passaggi:

  1. Nel file src/app/page.js , trova il componente <Home /> server e rivedi la chiamata alla funzione getRestaurants , che recupera un elenco di ristoranti al tempo di esecuzione del server. Si implementa la funzione getRestaurants nei seguenti passaggi.
  2. Nel file src/lib/firebase/firestore.js , sostituire i Funzioni applyQueryFilters e getRestaurants con il seguente codice:
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. Aggiorna l'app Web. Le immagini del ristorante appaiono come piastrelle sulla pagina.

Verificare che gli elenchi di ristoranti caricano a tempo di esecuzione del server

Utilizzando il framework Next.js, potrebbe non essere ovvio quando i dati vengono caricati al tempo di esecuzione del server o al tempo di esecuzione sul lato client.

Per verificare che gli elenchi di ristoranti caricano a tempo di esecuzione del server, seguire questi passaggi:

  1. Nell'app Web, Apri DevTools e Disabilita JavaScript .

Disabilita JavaScipt in DevTools

  1. Aggiorna l'app Web. Gli elenchi dei ristoranti sono ancora caricati. Le informazioni sul ristorante vengono restituite nella risposta del server. Quando JavaScript è abilitato, le informazioni sul ristorante vengono idratate attraverso il codice JavaScript sul lato client.
  2. In DevTools, REIDABILE JavaScript .

Ascolta gli aggiornamenti del ristorante con Cloud Firestore Snapshot Ascoltars

Nella sezione precedente, hai visto come il set iniziale di ristoranti caricato dal file src/app/page.js . Il file src/app/page.js è un componente del server ed è reso sul server, incluso il codice Firebase Data-Fetching.

Il file src/components/RestaurantListings.jsx è un componente client e può essere configurato per idratare il markup reso al server.

Per configurare il file src/components/RestaurantListings.jsx per idratare il markup rendering del server, seguire questi passaggi:

  1. Nel file src/components/RestaurantListings.jsx , osserva il seguente codice, che è già scritto per te:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

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

Questo codice invoca la funzione getRestaurantsSnapshot() , che è simile alla funzione getRestaurants() che hai implementato in un passaggio precedente. Tuttavia, questa funzione snapshot fornisce un meccanismo di callback in modo che il callback venga invocato ogni volta che viene apportata una modifica alla collezione del ristorante.

  1. Nel file src/lib/firebase/firestore.js , sostituire la funzione getRestaurantsSnapshot() con il seguente codice:
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;
}

Le modifiche apportate attraverso la pagina del database FireStore ora riflettono nell'app Web in tempo reale.

  1. Nell'app Web, seleziona 27Ca5d1e8ed8adfe.png > Aggiungi ristoranti campione . Se la funzione di istantanea è implementata correttamente, i ristoranti appaiono in tempo reale senza un aggiornamento della pagina.

8. Salva i dati utente dall'app Web

  1. Nel file src/lib/firebase/firestore.js , sostituire la funzione updateWithRating() con il seguente codice:
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()),
        });
};

Questo codice inserisce un nuovo documento Firestore che rappresenta la nuova revisione. Il codice aggiorna anche il documento FireStore esistente che rappresenta il ristorante con cifre aggiornate per il numero di valutazioni e la valutazione calcolata media.

  1. Sostituire la funzione addReviewToRestaurant() con il seguente codice:
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;
        }
}

Implementa un'azione del server Next.js

Un'azione del server Next.js fornisce un'API conveniente per accedere ai dati del modulo, come data.get("text") per ottenere il valore di testo dal payload di invio del modulo.

Per utilizzare un'azione server Next.js per elaborare l'invio del modulo di revisione, seguire questi passaggi:

  1. Nel file src/components/ReviewDialog.jsx , trova l'attributo action nell'elemento <form> .
<form action={handleReviewFormSubmission}>

Il valore dell'attributo action si riferisce a una funzione implementata nel passaggio successivo.

  1. Nel file src/app/actions.js , sostituire la funzione handleReviewFormSubmission() con il seguente codice:
// 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"),
        });
}

Aggiungi recensioni per un ristorante

Hai implementato il supporto per le comunicazioni di revisione, quindi ora puoi verificare che le tue recensioni siano inserite correttamente nel Cloud Firestore.

Per aggiungere una revisione e verificare che sia inserito nel Firestore di Cloud, segui questi passaggi:

  1. Nell'app Web, selezionare un ristorante dalla home page.
  2. Nella pagina del ristorante, fai clic 3e19beef78bb0d0e.png .
  3. Seleziona una valutazione a stella.
  4. Scrivere una recensione.
  5. Fai clic su Invia . La tua recensione appare nella parte superiore dell'elenco delle recensioni.
  6. In Cloud Firestore, cerca il riquadro Aggiungi documento per il documento del ristorante che hai esaminato e selezionarlo.
  7. Nel riquadro di raccolta Start , selezionare le valutazioni .
  8. Nel riquadro Aggiungi documento , trova il documento per la tua recensione per verificare che sia stato inserito come previsto.

Documenti nell'emulatore di Firestore

9. Salva i file con caricamento dell'utente dall'app Web

In questa sezione, aggiungi funzionalità in modo da poter sostituire l'immagine associata a un ristorante quando hai effettuato l'accesso. Si carica l'immagine in archiviazione Firebase e si aggiorna l'URL dell'immagine nel documento Cloud FireStore che rappresenta il ristorante.

Per salvare i file con caricamento dell'utente dall'app Web, seguire questi passaggi:

  1. Nel file src/components/Restaurant.jsx , osservare il codice che viene eseguito quando l'utente carica un file:
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 });
}

Non sono necessarie modifiche, ma si implementa il comportamento della funzione updateRestaurantImage() nelle seguenti fasi.

  1. Nel file src/lib/firebase/storage.js , sostituire le funzioni di updateRestaurantImage() e uploadImage() con il seguente codice:
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 funzione updateRestaurantImageReference() è già implementata per te. Questa funzione aggiorna un documento di ristorante esistente in Cloud FireStore con un URL di immagine aggiornato.

Verifica la funzionalità di immagini immagine

Per verificare che l'immagine carichi come previsto, seguire questi passaggi:

  1. Nell'app Web, verifica che hai effettuato l'accesso e seleziona un ristorante.
  2. Clic 7067EB41FEA41FF0.PNG e caricare un'immagine dal tuo filesystem. La tua immagine lascia il tuo ambiente locale e viene caricata su Cloud Storage. L'immagine appare immediatamente dopo averlo caricato.
  3. Passare a Cloud Storage per Firebase.
  4. Passa alla cartella che rappresenta il ristorante. L'immagine che hai caricato esiste nella cartella.

6cf3f9e2303c931c.png

10. Conclusione

Congratulazioni! Hai imparato come utilizzare Firebase per aggiungere funzionalità e funzionalità a un'app Next.js. In particolare, hai usato quanto segue:

Saperne di più