Mengintegrasikan Firebase dengan aplikasi Next.js

1. Sebelum memulai

Dalam codelab ini, Anda akan mempelajari cara mengintegrasikan Firebase dengan aplikasi web Next.js yang disebut Friendly Eats, yaitu situs yang menyediakan ulasan restoran.

Aplikasi web Friendly Eats

Aplikasi web yang sudah selesai menawarkan fitur berguna yang menunjukkan bagaimana Firebase dapat membantu Anda membangun aplikasi Next.js. Fitur tersebut mencakup:

  • Fungsi login dengan Google dan logout: Dengan aplikasi web yang sudah selesai, Anda dapat login dengan Google dan logout. Login dan persistensi pengguna dikelola sepenuhnya melalui Firebase Authentication.
  • Gambar: Aplikasi web yang sudah selesai memungkinkan pengguna yang login mengupload gambar restoran. Aset gambar disimpan di Cloud Storage for Firebase. Firebase JavaScript SDK menyediakan URL publik untuk gambar yang diupload. URL publik ini kemudian disimpan di dokumen restoran yang relevan di Cloud Firestore.
  • Ulasan: Dengan aplikasi web yang sudah selesai, pengguna yang login dapat memposting ulasan tentang restoran yang terdiri dari rating bintang dan pesan berbasis teks. Informasi ulasan disimpan di Cloud Firestore.
  • Filter: Dengan aplikasi web yang sudah selesai, pengguna yang login dapat memfilter daftar restoran berdasarkan kategori, lokasi, dan harga. Anda juga dapat menyesuaikan metode pengurutan yang digunakan. Data diakses dari Cloud Firestore, dan kueri Firestore diterapkan berdasarkan filter yang digunakan.

Prasyarat

  • Pengetahuan tentang Next.js dan JavaScript

Yang akan Anda pelajari

  • Cara menggunakan Firebase dengan Router Aplikasi Next.js dan rendering sisi server.
  • Cara mempertahankan gambar di Cloud Storage for Firebase.
  • Cara membaca dan menulis data di database Cloud Firestore.
  • Cara menggunakan login dengan Google menggunakan Firebase JavaScript SDK.

Yang Anda butuhkan

  • Git
  • Java Development Kit
  • Node.js versi stabil terbaru
  • Browser pilihan Anda, seperti Google Chrome
  • Lingkungan pengembangan dengan editor kode dan terminal
  • Akun Google untuk pembuatan dan pengelolaan project Firebase Anda
  • Kemampuan untuk mengupgrade project Firebase ke paket harga Blaze

2. Menyiapkan lingkungan pengembangan

Codelab ini menyediakan codebase awal aplikasi dan mengandalkan Firebase CLI.

Mendownload repositori

  1. Di terminal Anda, clone repositori GitHub codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. Repositori GitHub berisi project contoh untuk beberapa platform. Namun, codelab ini hanya menggunakan direktori nextjs-start. Perhatikan direktori berikut:
    • nextjs-start: berisi kode awal yang menjadi tempat Anda membuat kode.
    • nextjs-end: berisi kode solusi untuk aplikasi web yang sudah selesai.
  3. Di terminal Anda, buka direktori nextjs-start dan instal dependensi yang diperlukan:
    cd friendlyeats-web/nextjs-start
    npm install
    

Menginstal atau mengupdate Firebase CLI

Jalankan perintah berikut untuk memverifikasi bahwa Anda telah menginstal Firebase CLI dan menggunakan v12.5.4 atau yang lebih tinggi:

firebase --version
  • Jika Anda sudah menginstal Firebase CLI, tetapi bukan v12.5.4 atau yang lebih tinggi, update Firebase CLI:
    npm update -g firebase-tools
    
  • Jika Anda belum mengintal Firebase CLI, instal sekarang:
    npm install -g firebase-tools
    

Jika Anda tidak dapat menginstal Firebase CLI karena error izin, lihat dokumentasi npm atau gunakan opsi penginstalan lainnya.

Login ke Firebase

  1. Jalankan perintah berikut untuk login ke Firebase CLI:
    firebase login
    
  2. Bergantung pada apakah Anda ingin Firebase mengumpulkan data, masukkan Y atau N.
  3. Di browser, pilih akun Google Anda, lalu klik Allow.

3. Menyiapkan project Firebase

Di bagian ini, Anda akan menyiapkan project Firebase dan mengaitkan aplikasi web Firebase dengan project tersebut. Anda juga akan menyiapkan layanan Firebase yang digunakan oleh aplikasi web contoh.

Membuat project Firebase

  1. Di Firebase console, klik Create project.
  2. Di kotak teks Enter your project name, masukkan FriendlyEats Codelab (atau nama project pilihan Anda), lalu klik Continue.
  3. Untuk codelab ini, Anda tidak memerlukan Google Analytics. Oleh karena itu, nonaktifkan opsi Enable Google Analytics for this project.
  4. Klik Create project.
  5. Tunggu hingga project Anda disediakan, lalu klik Continue.
  6. Di project Firebase Anda, buka Project Settings. Catat project ID Anda karena Anda akan memerlukannya nanti. ID unik ini adalah cara project Anda diidentifikasi (misalnya, di Firebase CLI).

Menambahkan aplikasi web ke project Firebase

  1. Buka Project overview di project Firebase Anda, lalu klik e41f2efdd9539c31.png Web.
  2. Di kotak teks App nickname, masukkan nama panggilan aplikasi yang mudah diingat, seperti My Next.js app.
  3. Centang kotak Also set up Firebase Hosting for this app.
  4. Klik Register app > Next > Next > Continue to konsol.

Mengupgrade paket harga Firebase Anda

Untuk menggunakan framework web, project Firebase Anda harus menggunakan paket harga Blaze, yang berarti terkait dengan akun Penagihan Cloud.

  • Akun Penagihan Cloud memerlukan metode pembayaran, seperti kartu kredit.
  • Jika Anda baru menggunakan Firebase dan Google Cloud, periksa apakah Anda memenuhi syarat untuk mendapatkan kredit sebesar $300 dan akun Penagihan Cloud Uji Coba Gratis.

Namun, perhatikan bahwa penyelesaian codelab ini tidak akan menimbulkan biaya sebenarnya.

Untuk mengupgrade project Anda ke paket Blaze, ikuti langkah-langkah berikut:

  1. Di Firebase console, pilih upgrade your plan.
  2. Pada dialog yang muncul, pilih paket Blaze, lalu ikuti petunjuk di layar untuk mengaitkan project Anda dengan akun Penagihan Cloud.
    Jika perlu membuat akun Penagihan Cloud, Anda mungkin perlu kembali ke alur upgrade di Firebase console untuk menyelesaikan upgrade.

Menyiapkan layanan Firebase di Firebase console

Menyiapkan Authentication

  1. Di Firebase console, buka Authentication.
  2. Klik Get started.
  3. Di kolom Additional providers, klik Google > Enable.
  4. Di kotak teks Public-facing name for project, masukkan nama yang mudah diingat, seperti My Next.js app.
  5. Dari drop-down Support email for project, pilih alamat email Anda.
  6. Klik Save.

Menyiapkan Cloud Firestore

  1. Di Firebase console, buka Firestore.
  2. Klik Create database > Start in test mode > Next.
    Di codelab ini, Anda akan menambahkan Aturan Keamanan untuk mengamankan data. Jangan mendistribusikan atau mengekspos aplikasi ke publik tanpa menambahkan Aturan Keamanan untuk database Anda.
  3. Gunakan lokasi default atau pilih lokasi pilihan Anda.
    Untuk aplikasi yang sebenarnya, Anda harus memilih lokasi yang dekat dengan pengguna. Perlu diperhatikan bahwa lokasi ini tidak dapat diubah nanti, dan juga akan secara otomatis menjadi lokasi bucket Cloud Storage default Anda (langkah berikutnya).
  4. Klik Done.

Menyiapkan Cloud Storage for Firebase

  1. Di Firebase console, buka Storage.
  2. Klik Get started > Start in test mode > Next.
    Di codelab ini, Anda akan menambahkan Aturan Keamanan untuk mengamankan data. Jangan mendistribusikan atau mengekspos aplikasi ke publik tanpa menambahkan Aturan Keamanan untuk bucket Storage Anda.
  3. Lokasi bucket Anda seharusnya sudah dipilih (karena Anda menyiapkan Firestore di langkah sebelumnya).
  4. Klik Done.

4. Meninjau codebase awal

Di bagian ini, Anda akan meninjau beberapa area codebase awal aplikasi yang akan ditambahi fungsi dalam codelab ini.

Struktur folder dan file

Tabel berikut berisi ringkasan struktur folder dan file aplikasi:

Folder dan file

Deskripsi

src/components

Komponen React untuk filter, header, detail restoran, dan ulasan

src/lib

Fungsi utilitas yang tidak harus terikat dengan React atau Next.js

src/lib/firebase

Kode khusus Firebase dan konfigurasi Firebase

public

Aset statis di aplikasi web, seperti ikon

src/app

Memilih rute dengan Router Aplikasi Next.js

src/app/restaurant

Pengendali rute API

package.json dan package-lock.json

Dependensi project dengan npm

next.config.js

Konfigurasi khusus Next.js (tindakan server diaktifkan)

jsconfig.json

Konfigurasi layanan bahasa JavaScript

Komponen server dan klien

Aplikasi ini adalah aplikasi web Next.js yang menggunakan Router Aplikasi. Rendering server digunakan di seluruh aplikasi. Misalnya, file src/app/page.js adalah komponen server yang bertanggung jawab atas halaman utama. File src/components/RestaurantListings.jsx adalah komponen klien yang ditunjukkan oleh perintah "use client" di awal file.

Pernyataan impor

Anda mungkin melihat pernyataan impor seperti berikut:

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

Aplikasi menggunakan simbol @ untuk menghindari jalur impor relatif yang kaku dan dimungkinkan oleh alias jalur.

API khusus Firebase

Semua kode Firebase API digabungkan dalam direktori src/lib/firebase. Setiap komponen React kemudian mengimpor fungsi yang digabungkan dari direktori src/lib/firebase, bukan mengimpor fungsi Firebase secara langsung.

Data tiruan

Data restoran dan ulasan tiruan terdapat dalam file src/lib/randomData.js. Data dari file tersebut disusun dalam kode di file src/lib/fakeRestaurants.js.

5. Menyiapkan hosting lokal dengan emulator Firebase Hosting

Di bagian ini, Anda akan menggunakan emulator Firebase Hosting untuk menjalankan aplikasi web Next.js secara lokal.

Di akhir bagian ini, emulator Firebase Hosting menjalankan aplikasi Next.js, sehingga Anda tidak perlu menjalankan Next.js dalam proses terpisah dari emulator.

Mendownload dan menggunakan akun layanan Firebase

Aplikasi web yang akan Anda bangun di codelab ini menggunakan rendering sisi server dengan Next.js.

Firebase Admin SDK untuk Node.js digunakan untuk memastikan Aturan Keamanan berfungsi dari kode sisi server. Untuk menggunakan API di Firebase Admin, Anda perlu mendownload dan menggunakan akun layanan Firebase dari Firebase console.

  1. Di Firebase console, buka halaman Service Accounts di Project settings Anda.
  2. Klik Generate new private key > Generate Key.
  3. Setelah file didownload ke sistem file Anda, dapatkan jalur lengkap ke file tersebut.
    Misalnya, jika Anda mendownload file ke direktori Downloads, jalur lengkapnya mungkin terlihat seperti ini: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. Di terminal Anda, setel variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS ke jalur kunci pribadi yang Anda download. Di lingkungan Unix, perintahnya mungkin terlihat seperti ini:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Biarkan terminal ini tetap terbuka dan gunakan selama sisa codelab ini, karena variabel lingkungan mungkin akan hilang jika Anda memulai sesi terminal baru.
    Jika membuka sesi terminal baru, Anda harus menjalankan kembali perintah sebelumnya.

Menambahkan konfigurasi Firebase ke kode aplikasi web

  1. Di Firebase console, buka Project settings.
  2. Di panel SDK setup and configuration, cari variabel firebaseConfig, lalu salin properti dan nilainya.
  3. Buka file .env di editor kode Anda, dan isi nilai variabel lingkungan dengan nilai konfigurasi dari Firebase console.
  4. Dalam file, ganti properti yang ada dengan properti yang Anda salin.
  5. Simpan file.

Menginisialisasi aplikasi web dengan project Firebase

Untuk menghubungkan aplikasi web ke project Firebase Anda, ikuti langkah-langkah berikut:

  1. Di terminal Anda, pastikan framework web diaktifkan di Firebase:
    firebase experiments:enable webframeworks
    
  2. Inisialisasi Firebase:
    firebase init
    
  3. Pilih opsi berikut:
    • Firestore: Mengonfigurasi aturan keamanan dan mengindeks file untuk Firestore
    • Hosting: Mengonfigurasi file untuk Firebase Hosting dan (secara opsional) menyiapkan deployment GitHub Action
    • Storage: Mengonfigurasi file aturan keamanan untuk Cloud Storage
    • Emulator: Menyiapkan emulator lokal untuk produk Firebase
  4. Pilih Use an existing project, lalu masukkan project ID yang sebelumnya Anda catat.
  5. Pilih nilai default untuk semua pertanyaan berikutnya hingga Anda mencapai pertanyaan In which region would you like to host server-side content, if applicable?. Terminal menampilkan pesan yang mendeteksi codebase Next.js yang ada di direktori saat ini.
  6. Untuk pertanyaan In which region would you like to host server-side content, if applicable?, pilih lokasi yang sebelumnya Anda pilih untuk Firestore dan Cloud Storage.
  7. Pilih nilai default untuk semua pertanyaan berikutnya sampai Anda mencapai pertanyaan Which Firebase emulators do you want to set up?. Untuk pertanyaan ini, pilih Functions emulator and Hosting emulator.
  8. Pilih nilai default untuk semua pertanyaan lainnya.

Men-deploy Aturan Keamanan

Kode ini sudah memiliki kumpulan Aturan Keamanan untuk Firestore dan Cloud Storage for Firebase. Setelah Anda men-deploy Aturan Keamanan, data dalam database dan bucket akan lebih terlindungi dari penyalahgunaan.

  1. Untuk men-deploy Aturan Keamanan ini, jalankan perintah ini di terminal Anda:
    firebase deploy --only firestore:rules,storage
    
  2. Jika ditanya: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", pilih Yes.

Memulai emulator Hosting

  1. Di terminal Anda, mulai emulator Hosting:
    firebase emulators:start --only hosting
    
    Terminal Anda merespons dengan port tempat Anda dapat menemukan emulator Hosting, misalnya http://localhost:5000/.

Terminal yang menunjukkan bahwa Emulator Hosting sudah siap

  1. Di browser, buka URL dengan emulator Firebase Hosting.
  2. Jika Anda melihat error di halaman web yang dimulai seperti ini: "Error: Firebase session cookie has incorrect...", Anda perlu menghapus semua cookie di lingkungan localhost Anda. Untuk melakukannya, ikuti petunjuk di delete cookies | DevTools Documentation.

Error sesi cookie

Menghapus cookie di DevTools

Sekarang Anda dapat melihat aplikasi web awal. Meskipun Anda melihat aplikasi web di URL localhost, aplikasi ini menggunakan layanan Firebase sebenarnya yang dikonfigurasi di konsol Anda.

6. Menambahkan autentikasi ke aplikasi web

Di bagian ini, Anda akan menambahkan autentikasi ke aplikasi web sehingga Anda dapat login ke aplikasi tersebut.

Mengimplementasikan fungsi login dan logout

  1. Di file src/lib/firebase/auth.js, ganti fungsi onAuthStateChanged, signInWithGoogle, dan signOut dengan kode berikut:
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);
        }
}

Kode ini menggunakan Firebase API berikut:

Firebase API

Deskripsi

GoogleAuthProvider

Membuat instance penyedia autentikasi Google.

signInWithPopup

Memulai alur autentikasi berbasis dialog.

auth.signOut

Memproses logout pengguna.

Dalam file src/components/Header.jsx, kode sudah memanggil fungsi signInWithGoogle dan signOut.

  1. Di aplikasi web, muat ulang halaman dan klik Sign in with Google. Aplikasi web tidak diupdate, sehingga tidak jelas apakah login berhasil atau tidak.

Berlangganan perubahan autentikasi

Untuk berlangganan perubahan autentikasi, ikuti langkah-langkah berikut:

  1. Buka file src/components/Header.jsx.
  2. Ganti fungsi useUserSession dengan kode berikut:
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;
}

Kode ini menggunakan hook state React untuk mengupdate pengguna saat fungsi onAuthStateChanged menentukan bahwa ada perubahan pada status autentikasi.

Memverifikasi perubahan

Tata letak root di file src/app/layout.js merender header dan meneruskan pengguna, jika tersedia, sebagai properti.

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

Ini berarti komponen <Header> akan merender data pengguna, jika tersedia, selama waktu proses server. Jika ada update autentikasi selama siklus proses halaman setelah pemuatan halaman awal, pengendali onAuthStateChanged akan menanganinya.

Sekarang saatnya menguji aplikasi web dan memverifikasi apa yang telah Anda buat.

Untuk memverifikasi perilaku autentikasi baru, ikuti langkah-langkah berikut:

  1. Di browser, muat ulang aplikasi web. Nama tampilan Anda akan muncul di header.
  2. Logout dan login lagi. Halaman diupdate secara real time tanpa memuat ulang halaman. Anda dapat mengulangi langkah ini dengan pengguna lain.
  3. Opsional: Klik kanan aplikasi web, pilih View page source, lalu telusuri nama tampilan. Nama tampilan akan muncul di sumber HTML mentah yang ditampilkan dari server.

7. Melihat informasi restoran

Aplikasi web menyertakan data tiruan untuk restoran dan ulasan.

Menambahkan satu atau beberapa restoran

Untuk memasukkan data restoran tiruan ke database Cloud Firestore lokal Anda, ikuti langkah-langkah berikut:

  1. Di aplikasi web, pilih 2cf67d488d8e6332.png > Add sample restaurants.
  2. Di Firebase console di halaman Firestore Database, pilih restaurants. Anda akan melihat dokumen tingkat teratas dalam koleksi restoran, yang masing-masing mewakili restoran.
  3. Klik beberapa dokumen untuk menjelajahi properti dokumen restoran.

Menampilkan daftar restoran

Database Cloud Firestore Anda sekarang memiliki restoran yang dapat ditampilkan oleh aplikasi web Next.js.

Untuk menentukan kode pengambilan data, ikuti langkah-langkah berikut:

  1. Dalam file src/app/page.js, temukan komponen server <Home />, dan tinjau panggilan ke fungsi getRestaurants, yang mengambil daftar restoran pada waktu proses server. Anda akan menerapkan fungsi getRestaurants dalam langkah-langkah berikut.
  2. Di file src/lib/firebase/firestore.js, ganti fungsi applyQueryFilters dan getRestaurants dengan kode berikut:
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. Muat ulang aplikasi web. Gambar restoran muncul sebagai tile di halaman.

Memastikan listingan restoran dimuat pada waktu proses server

Dengan menggunakan framework Next.js, mungkin akan sulit untuk mengetahui kapan data dimuat pada waktu proses server atau waktu proses sisi klien.

Untuk memverifikasi bahwa listingan restoran dimuat pada waktu proses server, ikuti langkah-langkah berikut:

  1. Di aplikasi web, buka DevTools dan nonaktifkan JavaScript.

Menonaktifkan JavaScipt di DevTools

  1. Muat ulang aplikasi web. Listingan restoran masih dimuat. Informasi restoran ditampilkan di respons server. Jika JavaScript diaktifkan, informasi restoran dihidrasi melalui kode JavaScript sisi klien.
  2. Di DevTools, aktifkan kembali JavaScript.

Memproses update restoran dengan pemroses snapshot Cloud Firestore

Di bagian sebelumnya, Anda telah melihat cara kumpulan restoran awal dimuat dari file src/app/page.js. File src/app/page.js adalah komponen server dan dirender di server, termasuk kode pengambilan data Firebase.

File src/components/RestaurantListings.jsx adalah komponen klien dan dapat dikonfigurasi untuk menghidrasi markup yang dirender server.

Untuk mengonfigurasi file src/components/RestaurantListings.jsx guna menghidrasi markup yang dirender server, ikuti langkah-langkah berikut:

  1. Dalam file src/components/RestaurantListings.jsx, amati kode berikut, yang sudah ditulis untuk Anda:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

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

Kode ini memanggil fungsi getRestaurantsSnapshot(), yang mirip dengan fungsi getRestaurants() yang Anda implementasikan di langkah sebelumnya. Namun, fungsi snapshot ini menyediakan mekanisme callback sehingga callback dipanggil setiap kali perubahan dilakukan pada koleksi restoran.

  1. Di file src/lib/firebase/firestore.js, ganti fungsi getRestaurantsSnapshot() dengan kode berikut:
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;
}

Perubahan yang dilakukan melalui halaman Database Firestore kini tercermin di aplikasi web secara real time.

  1. Di aplikasi web, pilih 27ca5d1e8ed8adfe.png > Add sample restaurants. Jika fungsi snapshot Anda diterapkan dengan benar, restoran akan muncul secara real time tanpa memuat ulang halaman.

8. Menyimpan data pengguna dari aplikasi web

  1. Di file src/lib/firebase/firestore.js, ganti fungsi updateWithRating() dengan kode berikut:
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()),
        });
};

Kode ini menyisipkan dokumen Firestore baru yang mewakili ulasan baru. Kode ini juga mengupdate dokumen Firestore yang ada yang mewakili restoran dengan angka yang diperbarui untuk jumlah rating dan rata-rata rating yang dihitung.

  1. Ganti fungsi addReviewToRestaurant() dengan kode berikut:
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;
        }
}

Mengimplementasikan Tindakan Server Next.js

Tindakan Server Next.js menyediakan API yang mudah digunakan untuk mengakses data formulir, seperti data.get("text") untuk mendapatkan nilai teks dari payload pengiriman formulir.

Untuk menggunakan Tindakan Server Next.js guna memproses pengiriman formulir peninjauan, ikuti langkah-langkah berikut:

  1. Dalam file src/components/ReviewDialog.jsx, temukan atribut action di elemen <form>.
<form action={handleReviewFormSubmission}>

Nilai atribut action mengacu pada fungsi yang Anda implementasikan di langkah berikutnya.

  1. Di file src/app/actions.js, ganti fungsi handleReviewFormSubmission() dengan kode berikut:
// 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"),
        });
}

Menambahkan ulasan restoran

Anda telah menerapkan dukungan untuk pengiriman ulasan, jadi sekarang Anda dapat memverifikasi bahwa ulasan Anda disisipkan ke Cloud Firestore dengan benar.

Untuk menambahkan ulasan dan memverifikasi bahwa ulasan tersebut disisipkan ke Cloud Firestore, ikuti langkah-langkah berikut:

  1. Di aplikasi web, pilih restoran dari halaman beranda.
  2. Di halaman restoran, klik 3e19beef78bb0d0e.png.
  3. Pilih rating bintang.
  4. Tulis ulasan.
  5. Klik Submit. Ulasan Anda akan muncul di bagian atas daftar ulasan.
  6. Di Cloud Firestore, telusuri panel Add document untuk dokumen restoran yang telah Anda ulas dan pilih dokumen tersebut.
  7. Di panel Start collection, pilih ratings.
  8. Di panel Add document, temukan dokumen untuk peninjauan Anda guna memverifikasi bahwa dokumen tersebut disisipkan seperti yang diharapkan.

Dokumen di Emulator Firestore

9. Menyimpan file yang diupload pengguna dari aplikasi web

Di bagian ini, Anda menambahkan fungsi sehingga Anda dapat mengganti gambar yang terkait dengan restoran saat Anda login. Anda mengupload gambar ke Firebase Storage, dan mengupdate URL gambar di dokumen Cloud Firestore yang mewakili restoran.

Untuk menyimpan file yang diupload pengguna dari aplikasi web, ikuti langkah-langkah berikut:

  1. Di file src/components/Restaurant.jsx, amati kode yang berjalan saat pengguna mengupload 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 });
}

Perubahan tidak diperlukan, tetapi Anda menerapkan perilaku fungsi updateRestaurantImage() dalam langkah-langkah berikut.

  1. Di file src/lib/firebase/storage.js, ganti fungsi updateRestaurantImage() dan uploadImage() dengan kode berikut:
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);
}

Fungsi updateRestaurantImageReference() sudah diimplementasikan untuk Anda. Fungsi ini mengupdate dokumen restoran yang ada di Cloud Firestore dengan URL gambar yang diupdate.

Memverifikasi fungsi upload gambar

Untuk memastikan bahwa gambar diupload seperti yang diharapkan, ikuti langkah-langkah berikut:

  1. Di aplikasi web, pastikan Anda login dan pilih restoran.
  2. Klik 7067eb41fea41ff0.png lalu upload gambar dari sistem file Anda. Gambar Anda meninggalkan lingkungan lokal dan diupload ke Cloud Storage. Gambar akan langsung muncul setelah Anda menguploadnya.
  3. Buka Cloud Storage for Firebase.
  4. Buka folder yang mewakili restoran. Gambar yang Anda upload ada di folder.

6cf3f9e2303c931c.png

10. Kesimpulan

Selamat! Anda telah mempelajari cara menggunakan Firebase untuk menambahkan fitur dan fungsi ke aplikasi Next.js. Secara khusus, Anda telah menggunakan hal berikut:

Pelajari lebih lanjut