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

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并初始化项目

  1. 安装Firebase依赖:
npm install @react-native-firebase/app @react-native-firebase/database

(Expo项目替换为expo install @react-native-firebase/app @react-native-firebase/database)

  1. 在Firebase控制台创建项目,开启实时数据库,暂时设置测试模式规则(后续需修改为安全规则):
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
  1. 按照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;

关键注意点

  1. 数据转换:Firebase返回对象型数据,需用Object.values()转为数组适配FlatList。
  2. 资源映射:本地资源不能直接存储到Firebase,需通过标识映射或替换为远程URL。
  3. 实时监听:on('value')可实时同步数据变化,仅需单次读取时改用once('value')。
  4. 安全规则:测试完成后务必修改Firebase数据库规则,限制读写权限防止数据泄露。

内容的提问来源于stack exchange,提问作者Bashamlan Salem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:32:17