新增資料

新增資料可以利用addDoc(),在collection裡(如:user)新增文件內容,這個方式不需要提供doc id,firestore會自動產生doc id

import { collection, addDoc } from "firebase/firestore"; 

// Add a new document with a generated id.
const docRef = await addDoc(collection(db, "cities"), {
  name: "Tokyo",
  country: "Japan"
});
console.log("Document written with ID: ", docRef.id);

新增資料也可以利用setDoc(),在collection裡(如:user)更新文件內容,跟addDoc()不同的是需要提供id,當id不存在時,會利用id為doc id產生一個新的文件

import { doc, setDoc } from "firebase/firestore"; 

await setDoc(doc(db, "cities", "new-city-id"), data);

我們參考上面的範例,來修改一下我們上週的程式。

/app/product/useProduct.tsx

import { addDoc, collection, getDocs, getFirestore } from "firebase/firestore";
import app from "@/app/_firebase/config"
import { useEffect, useState } from "react";

export default function useProducts() {
  const db = getFirestore(app);
  const [products, setProducts] = useState<{ desc: string, price: number }[]>([
    { desc: "iPad", price: 20000 },
    { desc: "iPhone 8", price: 20000 },
    { desc: "iPhone X", price: 30000 }
  ])

  // let data = [
  //   { desc: "iPad", price: 20000 },
  //   { desc: "iPhone 8", price: 20000 },
  //   { desc: "iPhone X", price: 30000 }
  // ];
  useEffect(() => {
    async function fetchData() {
      let data: { desc: string, price: number }[] = [];
      const querySnapshot = await getDocs(collection(db, "product"));
      querySnapshot.forEach((doc) => {
        data.push({ desc: doc.data().desc, price: doc.data().price })
        console.log(`${doc.id} => ${doc.data()}`);
      });
      setProducts(() => [...data]);
    }
    fetchData();
  }, [db]);

  **async function addProduct(product: { desc: string, price: number }) {
    const db = getFirestore(app);
    const docRef = await addDoc(collection(db, "product"),
      { desc: product.desc, price: product.price });
    console.log("Document written with ID: ", docRef.id);
  }**
  return [products, setProducts**, addProduct**] as const;

}

/app/product/ProductList.tsx

取得回傳的addProduct

const [products, setProducts**, addProduct**] = useGetProducts();

加一個add(),利用addProduct()去新增產品

  **function add() {**
    **addProduct(newProduct);**
    setNewProduct({ ...newProduct, visible: false })
    console.log(products);
  }

點選按鈕改呼叫add()

<Button variant="contained" color="primary" onClick={**add**}>新增</Button>

我們會發現寫進去的資料是字串,不是數字。要解決這問題:

  const handleClick = function (e: React.ChangeEvent<HTMLInputElement>) {
    if (e.target.name === "price") {
      setNewProduct({ ...newProduct, [e.target.name]: **parseInt(e.target.value)** })
    }
    else {
      setNewProduct({ ...newProduct, [e.target.name]: e.target.value })
    }
  }

<aside> 📢 注意firestore的規則必須允許write,否則,會有錯誤:

</aside>

FirebaseError: The caller does not have permission

請將權限暫時改為:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone with your database reference to view, edit,
    // and delete all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // all client requests to your Firestore database will be denied until you Update
    // your rules
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2023, 12, 1);
    }
  }
}