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

如何在Expo中查询Firestore嵌套集合数据并渲染到Flatlist

Firestore嵌套集合读取并渲染到React Native FlatList实现方案

文档结构示意图

现有代码问题说明

  • 变量声明顺序错误:currentUserUID、todos、loading等变量在被ref、useEffect调用后才声明,会触发引用错误
  • 集合名不匹配:需求中要读取的集合路径为journal/userID/entries,但现有代码中写的是collection('entry'),名称不一致导致无法拉取数据
  • useEffect依赖数组为空:监听逻辑不会随用户身份变更更新,也容易触发闭包问题
  • 缺少FlatList渲染逻辑,无法将拿到的数据展示在界面上

修复后完整实现代码

import React, { useState, useEffect } from 'react';
import { View, TextInput, Button, FlatList, Text, ActivityIndicator } from 'react-native';
import firebase from '../firebase/config'; // 替换为你自己的firebase配置引入路径

function TextEntry() {
  // 优先声明所有状态与常量
  const [todo, setTodo] = useState('');
  const [loading, setLoading] = useState(true);
  const [todos, setTodos] = useState([]);
  const currentUserUID = firebase.auth().currentUser.uid;
  // 修正集合名为entries,匹配Firestore路径
  const ref = firebase
    .firestore()
    .collection('journal')
    .doc(currentUserUID)
    .collection('entries');

  useEffect(() => {
    const unsubscribe = ref.onSnapshot(querySnapshot => {
      const list = [];
      querySnapshot.forEach(doc => {
        const { title } = doc.data();
        list.push({
          id: doc.id,
          title,
        });
      });
      setTodos(list);
      if (loading) {
        setLoading(false);
      }
    });
    // 组件卸载时取消监听,避免内存泄漏
    return unsubscribe;
    // 补充依赖项,保证监听逻辑正确更新
  }, [currentUserUID, loading]);

  async function addTodo() {
    if (!todo.trim()) return;
    await ref.add({
      title: todo.trim(),
    });
    setTodo('');
  }

  // 加载态展示
  if (loading) {
    return <ActivityIndicator size="large" style={{ flex: 1, justifyContent: 'center' }} />;
  }

  return (
    <View style={{ flex: 1, padding: 16 }}>
      {/* 新增条目输入区 */}
      <View style={{ flexDirection: 'row', marginBottom: 20, gap: 8 }}>
        <TextInput
          style={{ flex: 1, borderWidth: 1, borderColor: '#ccc', borderRadius: 4, paddingHorizontal: 8 }}
          value={todo}
          onChangeText={setTodo}
          placeholder="输入日记标题"
        />
        <Button title="添加" onPress={addTodo} />
      </View>
      {/* FlatList渲染日记列表 */}
      <FlatList
        data={todos}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <View style={{ paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#eee' }}>
            <Text style={{ fontSize: 16 }}>{item.title}</Text>
          </View>
        )}
      />
    </View>
  );
}

export default TextEntry;

注意事项

  • 确保你的Firebase安全规则已经开放了journal/{userId}/entries集合的读写权限,否则会触发权限报错
  • 如果用户可能处于未登录状态,建议先添加登录状态判断,避免读取firebase.auth().currentUser为null时报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:00:01