React Native中如何将餐厅数据迁移至Firebase实时数据库并读取
将React Native本地餐厅数据迁移到Firebase实时数据库并读取
我正尝试将餐厅数据(图片、名称、价格等)存入Firebase实时数据库,并从该库读取数据,替代React Native中的本地数据文件。以下是我用FlatList读取本地假数据的代码:
const renderCategory =()=>{ return( <View style={{ height:80, marginTop:6 }}> <FlatList horizontal contentContainerStyle={{ // marginLeft:SIZES.base, paddingHorizontal:SIZES.base, }} showsHorizontalScrollIndicator={false} data={dummyData?.restaurantMenu} keyExtractor={item=>`${item.id}`} renderItem={({item,index})=>{ return( <TouchableOpacity style={{ height:60, width:80, marginHorizontal:4, marginTop:SIZES.base, justifyContent:'center', alignItems:'center', borderRadius:SIZES.radius, borderWidth:1, borderColor: select === index ? COLORS.gray2 : COLORS.gray2, //backgroundColor: select === index ? COLORS.primary : null }} onPress={()=> navigation.navigate('Menu',{item})} > <Image source={item.icon} resizeMode='contain' style={{ height:40, width:40, tintColor: select === index ? COLORS.gray3 : COLORS.gray }} /> <Text style={{ ...FONTS.h3, color: select === index ? COLORS.gray3 : COLORS.gray, fontFamily:'Courgette-Regular' }} >{item.name}</Text> </TouchableOpacity> ) }} /> </View> )
本地假数据文件代码:
export const restaurantMenu = [ { id: 1, name: "Western", foodType:'Western Food', rating: 4.8, categories: [1], icon: icons.western, photo: images.background_1, price: 20.00, menu:[ { id: 1, name: "Chicken Fajita", photo: images.Chicken_Fajita, description: "Grilled Chicken Breast, Onion, Bell Pepper, Fajita Sauce", price: 20.00, rating:3, reviews:89, }, { id: 2, name: "Cordon Bleu", photo: images.Cordon_Bleu, description: "Panne Fried Chicken Breast Stuffed with Mozzarella Cheese, Mushroom", price: 21.00, rating:4, reviews:90, }, ], }, { id: 2, name: "Burgers", rating: 4.5, categories: [2], icon: icons.burger, photo: images.background_2, price: 10.00, menu:[ { id: 3, name: "Beef Burger", photo: images.Beef_Burger, description: "Fresh Beef Patty, Lettuce, Mayonnaise Topped with Cheddar Cheese", price: 15.00, rating:3, reviews:89, }, { id: 4, name: "Chicken Burger", photo: images.Chicken_Burger, description: "Fresh Chicken Burger Patty, Lettuce, Garlic Sauce, Cocktail Sauce,", price: 15.00, rating:3, reviews:89, }, ] } ]
我希望将这些数据存入Firebase实时数据库,并从该库读取以替代本地文件,但尝试后未成功,请问该如何实现?
解决方案
步骤1:配置Firebase并初始化项目
- 安装Firebase依赖:
npm install @react-native-firebase/app @react-native-firebase/database
(Expo项目替换为expo install @react-native-firebase/app @react-native-firebase/database)
- 在Firebase控制台创建项目,开启实时数据库,暂时设置测试模式规则(后续需修改为安全规则):
{ "rules": { ".read": true, ".write": true } }
- 按照Firebase控制台指引,将配置信息添加到React Native项目中完成初始化。
步骤2:调整数据结构适配Firebase
Firebase实时数据库更适合对象型存储,将原数组改为以id为键的对象(同时处理本地资源引用问题):
const restaurantMenuData = { "1": { id: 1, name: "Western", foodType:'Western Food', rating: 4.8, categories: [1], icon: "western", // 用字符串标识本地图标,后续映射回资源 photo: "background_1", // 同理,若用远程图则替换为Storage下载URL price: 20.00, menu:{ "1": { id: 1, name: "Chicken Fajita", photo: "Chicken_Fajita", description: "Grilled Chicken Breast, Onion, Bell Pepper, Fajita Sauce", price: 20.00, rating:3, reviews:89, }, "2": { id: 2, name: "Cordon Bleu", photo: "Cordon_Bleu", description: "Panne Fried Chicken Breast Stuffed with Mozzarella Cheese, Mushroom", price: 21.00, rating:4, reviews:90, } } }, "2": { id: 2, name: "Burgers", rating: 4.5, categories: [2], icon: "burger", photo: "background_2", price: 10.00, menu:{ "3": { id: 3, name: "Beef Burger", photo: "Beef_Burger", description: "Fresh Beef Patty, Lettuce, Mayonnaise Topped with Cheddar Cheese", price: 15.00, rating:3, reviews:89, }, "4": { id: 4, name: "Chicken Burger", photo: "Chicken_Burger", description: "Fresh Chicken Burger Patty, Lettuce, Garlic Sauce, Cocktail Sauce,", price: 15.00, rating:3, reviews:89, } } } }
步骤3:上传数据到Firebase
方式1:手动上传(一次性操作)
在Firebase实时数据库控制台,创建restaurantMenu节点,直接粘贴调整后的JSON数据。
方式2:代码上传(动态数据场景)
import database from '@react-native-firebase/database'; const uploadData = async () => { try { await database().ref('restaurantMenu').set(restaurantMenuData); console.log('数据上传成功'); } catch (error) { console.error('上传失败:', error); } }; // 组件挂载时执行一次上传 useEffect(() => { uploadData(); }, []);
步骤4:从Firebase读取数据并替换本地数据源
修改组件逻辑,从Firebase获取数据并适配FlatList:
import { useState, useEffect } from 'react'; import database from '@react-native-firebase/database'; import { View, FlatList, TouchableOpacity, Image, Text } from 'react-native'; import icons from './path/to/icons'; import images from './path/to/images'; const YourComponent = ({ navigation }) => { const [restaurantMenu, setRestaurantMenu] = useState([]); const [select, setSelect] = useState(0); // 映射本地资源标识到实际资源 const getIcon = (iconKey) => { const iconMap = { western: icons.western, burger: icons.burger }; return iconMap[iconKey] || icons.default; }; const getImage = (imageKey) => { const imageMap = { background_1: images.background_1, background_2: images.background_2, Chicken_Fajita: images.Chicken_Fajita, Cordon_Bleu: images.Cordon_Bleu, Beef_Burger: images.Beef_Burger, Chicken_Burger: images.Chicken_Burger }; return imageMap[imageKey] || images.default; }; // 实时监听Firebase数据 useEffect(() => { const unsubscribe = database() .ref('restaurantMenu') .on('value', (snapshot) => { const data = snapshot.val(); if (data) { // 将对象转为数组适配FlatList const menuArray = Object.values(data); setRestaurantMenu(menuArray); } else { setRestaurantMenu([]); } }); // 组件卸载时取消监听 return () => unsubscribe(); }, []); const renderCategory = () => { return ( <View style={{ height: 80, marginTop: 6 }}> <FlatList horizontal contentContainerStyle={{ paddingHorizontal: SIZES.base }} showsHorizontalScrollIndicator={false} data={restaurantMenu} keyExtractor={(item) => `${item.id}`} renderItem={({ item, index }) => { return ( <TouchableOpacity style={{ height: 60, width: 80, marginHorizontal: 4, marginTop: SIZES.base, justifyContent: 'center', alignItems: 'center', borderRadius: SIZES.radius, borderWidth: 1, borderColor: select === index ? COLORS.gray2 : COLORS.gray2, }} onPress={() => { // 映射item中的资源标识为本地资源 const mappedItem = { ...item, icon: getIcon(item.icon), photo: getImage(item.photo), menu: item.menu ? Object.values(item.menu).map(menuItem => ({ ...menuItem, photo: getImage(menuItem.photo) })) : [] }; navigation.navigate('Menu', { item: mappedItem }); }} > <Image source={getIcon(item.icon)} resizeMode='contain' style={{ height: 40, width: 40, tintColor: select === index ? COLORS.gray3 : COLORS.gray }} /> <Text style={{ ...FONTS.h3, color: select === index ? COLORS.gray3 : COLORS.gray, fontFamily: 'Courgette-Regular' }} >{item.name}</Text> </TouchableOpacity> ); }} /> </View> ); }; return ( <View> {renderCategory()} </View> ); }; export default YourComponent;
关键注意点
- 数据转换:Firebase返回对象型数据,需用
Object.values()转为数组适配FlatList。 - 资源映射:本地资源不能直接存储到Firebase,需通过标识映射或替换为远程URL。
- 实时监听:
on('value')可实时同步数据变化,仅需单次读取时改用once('value')。 - 安全规则:测试完成后务必修改Firebase数据库规则,限制读写权限防止数据泄露。
内容的提问来源于stack exchange,提问作者Bashamlan Salem
相关产品推荐
相关产品推荐

