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

如何用Firebase+React Native Expo实现指定用户消息收发功能

实现管理员给特定用户发消息,用户登录后查看对应消息

现有代码问题分析

当前代码的核心问题是:

  1. 管理员端未指定目标用户ID,存储的userId是管理员自身的UID,无法定向发送
  2. 用户端未过滤消息,会获取所有用户的消息,无法只查看发给自己的内容

修改后的完整代码

管理员联系表单组件

import { useState } from 'react';
import { View, Alert } from 'react-native';
import { db, auth } from '../../firebase';
import { FormInput, AppButton } from './your-components-path'; // 替换为实际组件路径

const Contact = () => {
    const [adminName, setAdminName] = useState('')
    const [adminEmail, setAdminEmail] = useState('')
    const [targetUserId, setTargetUserId] = useState('')
    const [messageContent, setMessageContent] = useState('')
    const [loader, setLoader] = useState(false)

    function renderForm() {
        return (
            <View style={{ padding: 16 }}>
                {/* 管理员姓名输入 */}
                <FormInput
                    label='管理员姓名:'
                    value={adminName}
                    onChange={(value) => setAdminName(value)}
                    placeholder='输入你的姓名'
                />

                {/* 管理员邮箱输入 */}
                <FormInput
                    label='管理员邮箱:'
                    keyboardType='email-address'
                    value={adminEmail}
                    onChange={(value) => setAdminEmail(value)}
                    placeholder='输入你的邮箱'
                />

                {/* 目标用户UID输入 */}
                <FormInput
                    label='目标用户UID:'
                    value={targetUserId}
                    onChange={(value) => setTargetUserId(value)}
                    placeholder='输入要发送消息的用户UID'
                />

                {/* 消息内容输入 */}
                <FormInput
                    label='消息内容:'
                    placeholder='输入要发送的消息'
                    multiline={true}
                    numberOfLines={10}
                    inputStyle={{ height: 100 }}
                    value={messageContent}
                    onChange={(value) => setMessageContent(value)}
                />

                {/* 发送按钮 */}
                <View style={{ marginTop: 20 }}>
                    <AppButton
                        label='发送消息'
                        icon={icons.send}
                        disabled={!adminName || !targetUserId || !messageContent}
                        onPress={sendMessage}
                        loading={loader}
                    />
                </View>
            </View>
        )
    }

    const sendMessage = async () => {
        setLoader(true)
        try {
            await db.collection('messages').add({
                adminId: auth.currentUser?.uid,
                adminName: adminName,
                adminEmail: adminEmail,
                targetUserId: targetUserId,
                message: messageContent,
                sendTime: db.firestore.FieldValue.serverTimestamp()
            })
            Alert.alert('发送成功', '消息已发送给目标用户')
            // 重置表单
            setAdminName('')
            setAdminEmail('')
            setTargetUserId('')
            setMessageContent('')
        } catch (error) {
            Alert.alert('发送失败', error.message)
        } finally {
            setLoader(false)
        }
    }

    return renderForm()
}

export default Contact;

用户消息屏幕组件

import { useState, useEffect } from 'react';
import { View, Text, ScrollView, FlatList } from 'react-native';
import { db, auth } from '../../firebase';

const MessagesScreen = () => {
    const [messages, setMessages] = useState([]);
    const [loading, setLoading] = useState(true)

    const fetchUserMessages = async () => {
        try {
            const currentUserId = auth.currentUser?.uid
            if (!currentUserId) return

            const querySnapshot = await db.collection('messages')
                .where('targetUserId', '==', currentUserId)
                .orderBy('sendTime', 'desc')
                .get()
            
            const messageList = querySnapshot.docs.map(doc => ({
                id: doc.id,
                ...doc.data(),
                sendTime: doc.data().sendTime?.toDate().toLocaleString()
            }))
            setMessages(messageList)
        } catch (error) {
            console.error('获取消息失败:', error)
        } finally {
            setLoading(false)
        }
    }

    useEffect(() => {
        fetchUserMessages()
    }, [])

    if (loading) {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>加载消息中...</Text>
            </View>
        )
    }

    return (
        <ScrollView style={{ flex: 1 }}>
            {messages.length === 0 ? (
                <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 32 }}>
                    <Text>暂无消息</Text>
                </View>
            ) : (
                <FlatList
                    data={messages}
                    keyExtractor={(item) => item.id}
                    renderItem={({ item }) => (
                        <View style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#f0f0f0' }}>
                            <Text style={{ fontWeight: '600', marginBottom: 8 }}>管理员: {item.adminName}</Text>
                            <Text style={{ marginBottom: 4, lineHeight: 20 }}>{item.message}</Text>
                            <Text style={{ fontSize: 12, color: '#666' }}>{item.sendTime}</Text>
                        </View>
                    )}
                />
            )}
        </ScrollView>
    )
}

export default MessagesScreen;

核心修改点

  1. 管理员端:

    • 新增targetUserId输入框,明确指定消息接收用户的UID
    • 调整Firestore存储字段,区分管理员信息(adminId/adminName)和目标用户信息(targetUserId)
    • 使用Firebase服务器时间戳记录发送时间,确保时间准确性
    • 完善表单校验,避免空字段提交
  2. 用户端:

    • 添加where条件过滤,只获取targetUserId匹配当前登录用户UID的消息
    • 按发送时间倒序排列,优先显示最新消息
    • 补充加载状态和空消息提示,优化用户体验
    • 渲染时展示完整的消息信息(管理员姓名、内容、发送时间)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:40:24