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

如何在React Native Gifted Chat中添加图片消息?

解决React Native Gifted Chat图片消息发送与显示问题

问题核心

你的代码存在以下关键问题导致图片消息无法工作:

  • 图片按钮仅静态展示,无选择图片的交互逻辑
  • renderMessageImage被设为null,直接屏蔽了图片消息的渲染
  • 消息发送与监听逻辑只处理text字段,未包含图片的image字段
  • 函数组件中错误使用this.renderBubble(函数组件无需this)

修复方案

1. 安装图片选择依赖(Expo环境)

首先安装Expo ImagePicker用于选择图片:

expo install expo-image-picker

2. 修改组件代码

替换原NewMessage.js代码,关键点已标注:

import { TouchableOpacity, Text, View, Image } from 'react-native';
import { React, useState, useLayoutEffect, useCallback } from 'react'
import { auth, database } from '../firebase';
import { GiftedChat, InputToolbar, Send, Bubble } from 'react-native-gifted-chat';
import * as ImagePicker from 'expo-image-picker'; // 导入ImagePicker
import {
  collection,
  addDoc,
  orderBy,
  query,
  onSnapshot
} from 'firebase/firestore';

const NewMessage = () => {
  var nameMatch = auth?.currentUser?.email.match(/^([^@]*)@/);
  var name = nameMatch ? nameMatch[1] : null;
  const [messages, setMessages] = useState([]);

  useLayoutEffect(() => {
    const collectionRef = collection(database, 'chats');
    const q = query(collectionRef, orderBy('createdAt', 'desc'));

    const unsubscribe = onSnapshot(q, querySnapshot => {
      setMessages(
        querySnapshot.docs.map(doc => ({
          _id: doc.data()._id,
          createdAt: doc.data().createdAt.toDate(),
          text: doc.data().text,
          image: doc.data().image, // 新增:提取图片字段
          user: doc.data().user
        }))
      );
    });
    return unsubscribe;
  }, []);

  const onSend = useCallback((messages = []) => {
    setMessages(previousMessages => GiftedChat.append(previousMessages, messages));
    const { _id, createdAt, text, user, image } = messages[0];    
    addDoc(collection(database, 'chats'), {
      _id,
      createdAt,
      text, // 保留文本字段
      image, // 新增:存储图片字段
      user
    });
  }, []);

  // 新增:图片选择逻辑
  const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      quality: 0.5,
    });

    if (!result.canceled) {
      // 构造图片消息并发送
      const newMessage = {
        _id: Math.random().toString(36).substring(7),
        createdAt: new Date(),
        image: result.assets[0].uri,
        user: {
          _id: auth?.currentUser?.email,
          name: name,
          avatar: 'https://i.pravatar.cc/300'
        }
      };
      onSend([newMessage]);
    }
  };

  const customInputToolbar = props => { // 修正函数名拼写
    return (
      <InputToolbar
        {...props}
        containerStyle={{
          backgroundColor: "white",
          border: "none",
          padding: 5,
        }}
      />
    );
  };

  const customSend = props => {
    return (
      <>
        <Send {...props}>
          <View style={{ justifyContent: 'center', height: '100%', marginRight: 10 }}>
            <Image source={require("../assets/send.png")} style={{ width: 25, height: 25 }} />
          </View>
        </Send>
        <View style={{ justifyContent: 'center', height: '100%', marginRight: 10 }}>
          <Image source={require("../assets/play.png")} style={{ width:25, height:25 }} />
        </View>
        {/* 新增:给图片按钮添加TouchableOpacity绑定选择事件 */}
        <TouchableOpacity onPress={pickImage}>
          <View style={{ justifyContent: 'center', height: '100%', marginRight: 10 }}>
            <Image source={require("../assets/picture.png")} style={{ width:25, height:25 }} />
          </View>
        </TouchableOpacity>
      </>
    )
  }

  const renderBubble = props => {
    return (
      <Bubble
        {...props}
        wrapperStyle={{
          left: {
            backgroundColor: '#f0f0f0',
          },
        }}
      />
    )
  }

  return (
    <View style={{ flex:1 }}>
      <GiftedChat
        messages={messages}
        renderBubble={renderBubble} // 修复:去掉this
        showAvatarForEveryMessage={true}
        showUserAvatar={true}
        renderUsernameOnMessage={true}
        onSend={messages => onSend(messages)}
        alwaysShowSend={true}
        renderInputToolbar={props => customInputToolbar(props)} // 修正函数名
        messagesContainerStyle={{
          backgroundColor: '#ffff'
        }}
        renderSend={props => customSend(props)}
        textInputStyle={{
          backgroundColor: '#fff',
          borderRadius: 20,
        }}
        // 修复:自定义图片消息渲染
        renderMessageImage={(props) => (
          <Image
            style={{ width: 150, height: 150, borderRadius: 10 }}
            source={{ uri: props.currentMessage.image }}
          />
        )}
        user={{
          _id: auth?.currentUser?.email,
          name: name,
          avatar: 'https://i.pravatar.cc/300'
        }}
      />
    </View>
  )
}

export default NewMessage

3. 权限配置(Expo)

在app.json中添加图片访问权限:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSPhotoLibraryUsageDescription": "需要访问相册以发送图片消息"
      }
    },
    "android": {
      "permissions": ["READ_MEDIA_IMAGES"]
    }
  }
}

内容的提问来源于stack exchange,提问作者The Real Csharp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:01:01