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

React Native如何创建统一CRUD数据库管理文件实现组件复用?

问题解答

你的实现思路完全可行

你想要的「导出单个包含CRUD方法的对象、全局共享数据结构、后续平滑过渡到Firestore」的方案是完全可以实现的,之前的代码失效是因为用错了React组件的写法,下面直接给你正确的实现方式。

正确实现方案

一、本地数据版本(适配当前需求)

创建普通JS模块(无需React组件),数据只初始化一次,导出包含所有操作方法的对象,全局共享:

// database.js (不用jsx后缀,因为不是React组件)
// 全局初始化一次食谱数据,所有组件共享
let recipes = [
  {
    recipeId: '156',
    name: 'recipe1',
    isFavorit: true
  },
  {
    recipeId: '356',
    name: 'recipe2',
    isFavorit: true
  },
  {
    recipeId: '897',
    name: 'recipe3',
    isFavorit: false
  },
];

// 导出包含CRUD方法的统一对象
export default {
  // 获取食谱列表(返回副本避免外部直接修改原数据)
  getFolderList() {
    return [...recipes];
  },
  // 删除指定食谱
  deleteItem(recipeId) {
    recipes = recipes.filter(item => item.recipeId !== recipeId);
    return this.getFolderList();
  },
  // 添加新食谱
  addItem(newRecipe) {
    const newItem = {
      recipeId: Date.now().toString(), // 简单生成唯一ID
      ...newRecipe,
      isFavorit: newRecipe.isFavorit ?? false
    };
    recipes.push(newItem);
    return newItem;
  },
  // 切换收藏状态
  toggleFavorite(recipeId) {
    recipes = recipes.map(item => 
      item.recipeId === recipeId ? {...item, isFavorit: !item.isFavorit} : item
    );
    return this.getFolderList();
  }
};

组件中调用方式:

// otherFile.jsx
import database from './database';

// 获取食谱列表
const loadRecipes = () => {
  const folderList = database.getFolderList();
  setRecipes(folderList); // 用useState更新组件状态
};

// 删除食谱示例
const handleDelete = () => {
  const updatedList = database.deleteItem('156');
  setRecipes(updatedList);
};

二、适配Firestore的过渡版本

后续要做多用户和Firestore时,只需替换内部数据操作逻辑,方法名和调用方式完全不变,组件无需修改:

// database.js
import { getFirestore, collection, getDocs, deleteDoc, doc, addDoc, updateDoc, getDoc } from "firebase/firestore";
import { auth } from './firebaseConfig'; // 假设已配置Firebase Auth

const db = getFirestore();

export default {
  // 获取当前用户的食谱列表
  async getFolderList() {
    if (!auth.currentUser) return [];
    const querySnapshot = await getDocs(collection(db, `users/${auth.currentUser.uid}/recipes`));
    return querySnapshot.docs.map(doc => ({
      recipeId: doc.id,
      ...doc.data()
    }));
  },
  // 删除指定食谱
  async deleteItem(recipeId) {
    if (!auth.currentUser) return false;
    await deleteDoc(doc(db, `users/${auth.currentUser.uid}/recipes`, recipeId));
    return this.getFolderList();
  },
  // 添加新食谱
  async addItem(newRecipe) {
    if (!auth.currentUser) return null;
    const docRef = await addDoc(collection(db, `users/${auth.currentUser.uid}/recipes`), {
      ...newRecipe,
      isFavorit: newRecipe.isFavorit ?? false
    });
    return {
      recipeId: docRef.id,
      ...newRecipe,
      isFavorit: newRecipe.isFavorit ?? false
    };
  },
  // 切换收藏状态
  async toggleFavorite(recipeId) {
    if (!auth.currentUser) return false;
    const recipeDoc = doc(db, `users/${auth.currentUser.uid}/recipes`, recipeId);
    const docSnap = await getDoc(recipeDoc);
    if (!docSnap.exists()) return false;
    
    await updateDoc(recipeDoc, {
      isFavorit: !docSnap.data().isFavorit
    });
    return this.getFolderList();
  }
};

组件调用(注意异步处理):

// otherFile.jsx
import database from './database';
import { useState, useEffect } from 'react';

const [recipes, setRecipes] = useState([]);

useEffect(() => {
  const loadRecipes = async () => {
    const folderList = await database.getFolderList();
    setRecipes(folderList);
  };
  loadRecipes();
}, []);

// 删除食谱示例
const handleDelete = async () => {
  const updatedList = await database.deleteItem('156');
  setRecipes(updatedList);
};

为什么之前的代码失效?

你之前写的是React函数组件,DataBase是一个组件函数,必须通过<DataBase/>渲染才会执行内部逻辑,而且useState创建的状态是组件实例私有的,不能通过DataBase.getFolderList()直接调用——你定义的是组件内部的函数,并没有挂载到组件函数本身作为静态方法。

内容的提问来源于stack exchange,提问作者Lliira Magier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:35:03