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

React Native FlatList点击名称展示Firestore存储的客户完整详情咨询

实现方案

你当前代码中拉取Firestore数据时已经将单条客户的全量字段同步存储到了contacts数组的对应条目里,不需要额外发起二次数据库请求,直接用现有数据即可实现需求,以下是可直接落地的实现方法:

方案1:当前页弹窗展示(无需新增页面)

这是改动最小的实现方式,步骤如下:

  • 新增两个状态变量,分别存储选中的客户数据、控制详情弹窗的显隐
  • 将列表中的姓名字段包裹为可点击组件,点击时保存当前选中的客户数据、打开弹窗
  • 新增Modal组件,在弹窗内展示客户的所有完整信息
  • 同时修正原代码中TouchableOpacity嵌套在Text组件内的不规范写法,避免多端兼容问题

修改后的完整代码如下:

import React, { useEffect, useState } from 'react';
import { FlatList, StyleSheet, Text, TouchableOpacity, View, Modal } from 'react-native';
import { db } from "../firebase";

function DetailsScreen() {
  const [contacts, setContacts] = useState([]);
  // 新增详情弹窗相关状态
  const [selectedCustomer, setSelectedCustomer] = useState(null);
  const [showDetailModal, setShowDetailModal] = useState(false);

  var today = new Date();
  var dd = today.getDate();
  var mm = today.getMonth() + 1;
  var yyyy = today.getFullYear();
  today = mm + '/' + dd + '/' + yyyy;

  useEffect(() => {
    const fetchData = async () => {
      const data = await db.collection("contacts").where('createdDate', '<', today).get();
      setContacts(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
    };
    fetchData();
  }, []);

  function handleUpdate() {
    alert("updated")
  };

  function handleDelete() {
    alert("Successfully Removed")
  };

  // 渲染列表项
  const renderListItem = ({ item }) => (
    <View style={styles.listItem}>
      <Text style={styles.text1}> Student Details </Text>
      {/* 姓名改为可点击,触发详情弹窗 */}
      <TouchableOpacity onPress={() => {
        setSelectedCustomer(item);
        setShowDetailModal(true);
      }}>
        <Text style={styles.nameText}>姓名:{item.name}</Text>
      </TouchableOpacity>
      <Text style={styles.normalText}>邮箱:{item.email}</Text>
      <View style={styles.btnGroup}>
        <TouchableOpacity onPress={() => handleUpdate()} style={styles.btn}>
          <Text style={styles.btnText}> Update </Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => handleDelete()} style={styles.btn}>
          <Text style={styles.btnText}> Delete </Text>
        </TouchableOpacity>
      </View>
    </View>
  )

  return (
    <View style={styles.container}>
      <FlatList
        style={styles.list}
        data={contacts}
        renderItem={renderListItem}
        keyExtractor={item => item.id}
      />
      {/* 客户详情弹窗 */}
      <Modal visible={showDetailModal} animationType="slide">
        <View style={styles.modalContainer}>
          <TouchableOpacity 
            style={styles.closeBtn}
            onPress={() => setShowDetailModal(false)}
          >
            <Text style={styles.closeBtnText}>关闭</Text>
          </TouchableOpacity>
          {selectedCustomer && (
            <View>
              <Text style={styles.modalTitle}>客户完整详情</Text>
              <Text style={styles.modalItem}>姓名:{selectedCustomer.name}</Text>
              <Text style={styles.modalItem}>邮箱:{selectedCustomer.email}</Text>
              <Text style={styles.modalItem}>联系方式:{selectedCustomer.phone || '未填写'}</Text>
              <Text style={styles.modalItem}>所在区域:{selectedCustomer.area || '未填写'}</Text>
              <Text style={styles.modalItem}>创建时间:{selectedCustomer.createdDate || '无记录'}</Text>
              {/* 你可以继续添加其他需要展示的字段 */}
            </View>
          )}
        </View>
      </Modal>
    </View>
  )
};

export default DetailsScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 5,
  },
  listItem: {
    marginHorizontal: 20,
    borderBottomWidth: 1,
    paddingBottom: 10,
    paddingLeft: 15,
  },
  normalText: {
    fontSize: 15,
    fontStyle: 'italic',
    marginTop: 4
  },
  nameText: {
    fontSize: 15,
    fontStyle: 'italic',
    marginTop: 4,
    color: '#2385bb'
  },
  list: {
    flex: 1,
    paddingTop: 10,
    backgroundColor: '#fff'
  },
  text1: {
    fontSize: 18,
    fontWeight: 'bold',
    paddingTop:5
  },
  btnGroup: {
    flexDirection: 'row',
    marginTop: 10,
    gap: 20
  },
  btn: {
    borderWidth: 0.8,
    paddingHorizontal: 8,
    paddingVertical: 2
  },
  btnText: {
    fontSize: 14
  },
  modalContainer: {
    flex: 1,
    padding: 20,
    paddingTop: 50,
    backgroundColor: '#fff'
  },
  closeBtn: {
    alignSelf: 'flex-end',
    padding: 8
  },
  closeBtnText: {
    fontSize: 16,
    color: '#2385bb'
  },
  modalTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center'
  },
  modalItem: {
    fontSize: 16,
    marginBottom: 12,
    lineHeight: 22
  }
});

方案2:跳转独立详情页

如果你的项目使用React Navigation做路由管理,需要把详情放在独立页面,只需要修改姓名点击的逻辑即可:

  1. 先在路由配置中新增客户详情页CustomerDetail
  2. 点击姓名时携带当前客户数据跳转到详情页:
<TouchableOpacity onPress={() => {
  navigation.navigate('CustomerDetail', {
    customerInfo: item
  })
}}>
  <Text style={styles.nameText}>姓名:{item.name}</Text>
</TouchableOpacity>
  1. 在CustomerDetail页面通过route.params.customerInfo拿到客户全量数据,自行渲染需要展示的字段即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:39:02