如何在React Native Gifted Chat中实现Word/PDF文件的发送与显示功能?
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
propstorenderActions(you missed this earlier) so we can accessprops.onSendandprops.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
fileproperty (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
messagesarray passed toGiftedChat) includes these customfilefields—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.urito 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




