You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在React Native Gifted Chat中实现Word/PDF文件的发送与显示功能?

How to Send & Display Word/PDF Files with React Native Gifted Chat

Hey there! I'll walk you through every step to get file attachments working in your Gifted Chat setup—you're already halfway there with your current code, so let's fill in the gaps.


1. Confirm Dependencies & Basic renderActions Setup

Yes, you do need react-native-document-picker to let users select Word/PDF files from their device. If you haven't installed it yet, run this command in your project:

npm install react-native-document-picker
# or yarn add react-native-document-picker

Your existing renderActions is on the right track—this function lets you replace the default action button with custom options (like your "Document" picker). The key missing piece is connecting the selected file to Gifted Chat's message system.


2. Attach Selected Files to Gifted Chat Messages

You already have code to get the file object from DocumentPicker—now let's turn that into a sendable message. Here's how to update your renderActions function:

import DocumentPicker from 'react-native-document-picker';
import Ionicons from '@expo/vector-icons/Ionicons';
import { Actions } from 'react-native-gifted-chat';

// ... inside your chat component

renderActions(props) { // Don't forget to pass props here!
  return(
    <Actions 
      {...props} 
      options={{
        ['Select Document']: async () => {
          try {
            const result = await DocumentPicker.pick({
              type: [
                DocumentPicker.types.doc,
                DocumentPicker.types.docx,
                DocumentPicker.types.pdf
              ],
            });

            // 👇 Create a message object with file details
            const fileMessage = {
              _id: Date.now(), // Unique ID for the message
              text: '', // Leave text empty since this is a file message
              createdAt: new Date(),
              user: props.currentUser, // Use your app's current user object
              // Add custom file fields to identify and access the file
              file: {
                uri: result.uri,
                name: result.name,
                type: result.type,
                size: result.size
              }
            };

            // 👇 Send the message using Gifted Chat's built-in onSend
            props.onSend([fileMessage]);

          } catch(e){
            if(DocumentPicker.isCancel(e)){
              console.log("User cancelled file selection!")
            } else {
              console.error("Error picking file:", e);
            }
          }
        },
        ['Cancel']: () => console.log("Cancelled action")
      }}
      icon={() => (
        <Ionicons name={'add'} size={28} color={'#0077ff'} style={{left:0, bottom:0}} />
      )}
    />
  )
}

Key Changes:

  • We pass props to renderActions (you missed this earlier) so we can access props.onSend and props.currentUser.
  • After getting the file result, we build a message object with custom file properties (uri, name, type) that Gifted Chat will store alongside the message.
  • We call props.onSend([fileMessage]) to add this file message to your chat state (just like regular text messages).

3. Render File Messages with renderCustomView

Now that we're sending file messages, we need to display them instead of the empty text. Here's how to implement renderCustomView:

Step 1: Add the renderCustomView prop to your GiftedChat component

First, pass the function to Gifted Chat:

import { GiftedChat } from 'react-native-gifted-chat';

// ... inside your component's render() or return()

<GiftedChat
  messages={messages} // Your existing messages state array
  onSend={newMessages => onSend(newMessages)} // Your existing send handler
  user={currentUser} // Your app's current user object
  renderActions={props => this.renderActions(props)} // Pass your custom actions
  renderCustomView={props => this.renderCustomView(props)} // Add this line
/>

Step 2: Implement the renderCustomView function

This function checks if a message has a file property, then renders a custom UI for it:

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import Ionicons from '@expo/vector-icons/Ionicons';

// ... inside your chat component

renderCustomView(props) {
  const { currentMessage } = props;
  
  // Only render this if the message has a file attached
  if (currentMessage.file) {
    const isMyMessage = currentMessage.user._id === props.user._id;
    
    return (
      <View style={[
        styles.fileContainer,
        isMyMessage ? styles.myFile : styles.theirFile
      ]}>
        {/* File Icon: Show different icons for PDF vs Word */}
        <Ionicons 
          name={currentMessage.file.type.includes('pdf') ? 'file-pdf' : 'file-document'}
          size={32}
          color={isMyMessage ? '#fff' : '#0077ff'}
        />
        {/* File Name */}
        <Text style={[
          styles.fileName,
          isMyMessage ? styles.myFileName : styles.theirFileName
        ]}>
          {currentMessage.file.name}
        </Text>
        {/* Optional: Add a button to open the file */}
        <TouchableOpacity 
          style={styles.openButton}
          onPress={() => this.openFile(currentMessage.file.uri)}
        >
          <Text style={styles.openButtonText}>Open</Text>
        </TouchableOpacity>
      </View>
    );
  }
  
  // Return null if no file (Gifted Chat will render regular text messages)
  return null;
}

// Helper function to open the file (install react-native-file-viewer first)
async openFile(fileUri) {
  import FileViewer from 'react-native-file-viewer';
  
  try {
    await FileViewer.open(fileUri);
  } catch (error) {
    console.error("Error opening file:", error);
  }
}

// Add styles for the file view
const styles = StyleSheet.create({
  fileContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 10,
    borderRadius: 12,
    marginVertical: 5,
    maxWidth: '70%'
  },
  myFile: {
    backgroundColor: '#0077ff',
    alignSelf: 'flex-end'
  },
  theirFile: {
    backgroundColor: '#e5e5ea',
    alignSelf: 'flex-start'
  },
  fileName: {
    flex: 1,
    marginHorizontal: 10,
    fontSize: 14
  },
  myFileName: {
    color: '#fff'
  },
  theirFileName: {
    color: '#000'
  },
  openButton: {
    paddingHorizontal: 8,
    paddingVertical: 4,
    borderRadius: 6,
    backgroundColor: 'rgba(255,255,255,0.3)'
  },
  openButtonText: {
    color: '#fff',
    fontSize: 12
  }
});

What This Does:

  • Checks if the current message has a file property (the one we added in step 2).
  • Renders a styled container with:
    • An icon based on the file type (PDF vs Word).
    • The file name.
    • An "Open" button to launch the file (using react-native-file-viewer).
  • Adjusts styling based on whether the message is sent by the current user (right-aligned blue vs left-aligned gray).

Final Notes

  • Make sure your message state (the messages array passed to GiftedChat) includes these custom file fields—Gifted Chat will preserve them when storing messages.
  • For backend integration (sending files to a server), you'll need to upload the file from file.uri to your API, then store the server's file ID/URL in the message instead of the local URI.
  • If you're using Expo, you don't need to link packages manually (Document Picker and File Viewer work out of the box with Expo).

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

火山引擎 最新活动