如何在Firebase中新增数据而非覆盖旧数据?实现用户ID下存储书单
问题:Firebase存储书籍时覆盖旧数据,无法按用户ID隔离书单
我是一名初学者,正在开发一个CRUD项目以练习提升技能,该应用是一个Book list(书单)应用。目前我尝试在用户添加书籍时将数据存入Firebase,但操作时会覆盖旧数据。我的应用支持用户创建账号,希望将用户的书单存储在其对应的用户ID下,但不知如何实现。以下是我的代码,向Firebase创建新数据的逻辑位于submitHandler函数的第36行:
AddBook.jsx
import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import { addBook } from '../app/BooksSlice'; import { v4 as uuidv4 } from 'uuid'; import { auth, db } from '../firebase/firebase'; import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth'; import { addDoc, collection, doc, serverTimestamp, setDoc, } from 'firebase/firestore'; const AddBook = () => { const [data, setData] = useState({}); const inputHandler = event => { event.preventDefault(); const name = event.target.name; const value = event.target.value; setData({ ...data, [name]: value }); }; const dispatch = useDispatch(); const navigate = useNavigate(); const submitHandler = async event => { event.preventDefault(); const books = { id: uuidv4(), title: data.title, author: data.author }; dispatch(addBook(books)); // creating data to firebase try { await setDoc(doc(db, 'books', auth.currentUser.uid), { title: data.title, author: data.author, id: uuidv4(), time: serverTimestamp(), }); } catch (error) { console.log('Got and error while adding new data to firebase', error); } // Navigating to homepage after successfull login navigate('/show-books', { replace: true }); }; return ( <div className="container bg-dark py-3 px-5 mt-3 rounded"> <form onSubmit={submitHandler}> <div className="form-floating my-3"> <input name="title" type="text" className="form-control" placeholder="Title" value={data.title} onChange={event => inputHandler(event)} required /> <label>Title</label> </div> <div className="form-floating my-3"> <input name="author" type="text" className="form-control" placeholder="Author" value={data.author} onChange={event => inputHandler(event)} required /> <label>Author</label> </div> <button className="btn btn-lg btn-light" type="submit"> Add Book </button> </form> </div> ); }; export default AddBook;
解决方案
问题根源
你当前用setDoc(doc(db, 'books', auth.currentUser.uid))的写法,是直接把用户ID作为文档ID写入books集合。每次添加新书籍时,都会覆盖这个ID对应的文档,导致旧数据丢失。
正确实现方式
采用Firestore的子集合结构,为每个用户创建独立的书籍存储路径:users/{userId}/books。每个新书籍作为该子集合下的独立文档,既能避免覆盖,又能完美实现用户数据隔离。
修改后的代码逻辑
替换submitHandler中的Firebase写入部分:
const submitHandler = async event => { event.preventDefault(); const book = { id: uuidv4(), title: data.title, author: data.author }; dispatch(addBook(book)); // 修改后的Firebase数据写入逻辑 try { await addDoc(collection(db, 'users', auth.currentUser.uid, 'books'), { title: data.title, author: data.author, id: uuidv4(), time: serverTimestamp(), }); } catch (error) { console.log('添加数据到Firebase时出错', error); } navigate('/show-books', { replace: true }); };
补充说明
- 子集合结构是Firestore存储用户私有数据的最佳实践,后续查询用户书单时,只需针对
users/{当前用户ID}/books集合查询即可 - 若坚持使用
books根集合,也可以给每个书籍文档添加userId字段,查询时过滤当前用户ID,但子集合的方式数据隔离更清晰,性能更优
内容的提问来源于stack exchange,提问作者Mahbubul Hasan
相关产品推荐
相关产品推荐

