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

React Native Firestore统计页面:数据表格计数无法显示求助

问题:React Native Firestore数据无法在报表表格中显示

我需要制作一个报表数据表格,展示各城市相关数据的计数。目前已经获取到城市ID,且能在console.log中拿到计数数值,但无法在页面上显示。我尝试过以下方法均未解决:

  • 让GetDetails返回snap.size无效;
  • 使用FlatList无效;
  • 通过函数调用数据无效。

相关代码:

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, Button, ScrollView, FlatList } from 'react-native'
import firestore from '@react-native-firebase/firestore';
import { DataTable } from 'react-native-paper';


export default function TargetStaticsScreen() {

    const [zones, setZones] = useState([])

    function GetCities() {
        var z = [];
        firestore().collection('RandomZones').orderBy('City', 'asc').get().then(zones => {
            setZones(zones.docs)
        })

    }

    async function GetDetails({ cityid }) {
        let snap = await firestore().collection('RandomZones').doc(cityid).collection('targetlist').get()
        return (<DataTable.Cell key={cityid} numeric>{snap.size}</DataTable.Cell>
        )

    }
    function RemainingDots(cityid) {
        firestore().collection('RandomZones').doc(cityid).collection('targetlist').where('isUsed', '==', false).get().then(snap => {
            return snap.size;
        })
    }


    return (
        <ScrollView>
            <Button title='getdata' onPress={() => GetCities()} />
            <DataTable>
                <DataTable.Header>
                    <DataTable.Title>İl</DataTable.Title>
                    <DataTable.Title numeric>Toplam Nokta</DataTable.Title>
                    <DataTable.Title numeric>Kalan Nokta</DataTable.Title>
                    <DataTable.Title numeric>Aktif Nokta</DataTable.Title>
                    <DataTable.Title numeric>Aktif Nokta Tutar</DataTable.Title>
                </DataTable.Header>

                {zones.map((x) => {

                    return (
                        <DataTable.Row key={x.id}>
                            <DataTable.Cell>{x.id}</DataTable.Cell>
                            <GetDetails cityid={x.id} />
                            <DataTable.Cell numeric>{RemainingDots(x.id)}</DataTable.Cell>
                            <DataTable.Cell numeric>111</DataTable.Cell>
                            <DataTable.Cell numeric>111</DataTable.Cell>
                        </DataTable.Row>
                    )
                }
                )}

            </DataTable>
        </ScrollView>);
}

修复方案

核心问题是在组件渲染阶段直接调用异步函数获取数据——React无法处理异步返回的JSX或数值,导致页面无法正确渲染。以下是具体修复:

1. 重构数据获取逻辑,统一存入状态

不要在渲染时实时请求Firestore,而是在获取城市列表后,一次性拉取所有统计数据并存入状态:

import React, { useState } from 'react';
import { ScrollView, Button } from 'react-native'
import firestore from '@react-native-firebase/firestore';
import { DataTable } from 'react-native-paper';

export default function TargetStaticsScreen() {
    const [cityData, setCityData] = useState([])

    // 一次性获取所有城市及对应统计数据
    async function GetCityData() {
        // 先获取城市列表
        const zonesSnapshot = await firestore()
            .collection('RandomZones')
            .orderBy('City', 'asc')
            .get();
        
        // 批量请求每个城市的统计数据
        const cityStats = await Promise.all(
            zonesSnapshot.docs.map(async (cityDoc) => {
                // 总点数
                const totalSnap = await firestore()
                    .collection('RandomZones')
                    .doc(cityDoc.id)
                    .collection('targetlist')
                    .get();
                
                // 剩余点数
                const remainingSnap = await firestore()
                    .collection('RandomZones')
                    .doc(cityDoc.id)
                    .collection('targetlist')
                    .where('isUsed', '==', false)
                    .get();
                
                return {
                    id: cityDoc.id,
                    totalPoints: totalSnap.size,
                    remainingPoints: remainingSnap.size,
                    activePoints: 111, // 替换为你的实际活跃点数逻辑
                    activeAmount: 111  // 替换为你的实际活跃金额逻辑
                };
            })
        );

        setCityData(cityStats);
    }

    return (
        <ScrollView>
            <Button title='获取数据' onPress={GetCityData} />
            <DataTable>
                <DataTable.Header>
                    <DataTable.Title>城市</DataTable.Title>
                    <DataTable.Title numeric>总点数</DataTable.Title>
                    <DataTable.Title numeric>剩余点数</DataTable.Title>
                    <DataTable.Title numeric>活跃点数</DataTable.Title>
                    <DataTable.Title numeric>活跃点数金额</DataTable.Title>
                </DataTable.Header>

                {cityData.map((city) => (
                    <DataTable.Row key={city.id}>
                        <DataTable.Cell>{city.id}</DataTable.Cell>
                        <DataTable.Cell numeric>{city.totalPoints}</DataTable.Cell>
                        <DataTable.Cell numeric>{city.remainingPoints}</DataTable.Cell>
                        <DataTable.Cell numeric>{city.activePoints}</DataTable.Cell>
                        <DataTable.Cell numeric>{city.activeAmount}</DataTable.Cell>
                    </DataTable.Row>
                ))}
            </DataTable>
        </ScrollView>
    );
}

2. 原代码无效原因

  • GetDetails问题:React组件不能是异步函数,它返回的是Promise而非JSX元素,无法被渲染;
  • RemainingDots问题:函数是异步的,但直接在渲染中调用时,返回的是Promise而非实际数值,页面会显示undefined;
  • 状态缺失:仅存储城市列表,未存储统计数据,每次渲染重复请求数据,既低效又无法处理异步结果。

3. 优化建议

  • 添加加载状态,在数据获取时显示加载提示;
  • 若需要实时更新,可改用Firestore的onSnapshot监听数据变化;
  • 城市数量较多时,建议分页加载,避免一次性请求过多数据影响性能。

内容的提问来源于stack exchange,提问作者Sercan Eryaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 11:57:09