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
相关产品推荐
相关产品推荐

