You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:18:43