showcase/shell-docs/src/content/reference/react-native/hooks/useAttachments.mdx
useAttachments is the React Native counterpart of the web useAttachments hook. It manages picking, validating, uploading, and consuming file attachments for a chat, using expo-document-picker and expo-file-system in place of the web FileReader / <input type="file"> APIs.
The headless CopilotChat wires this hook up for you when you pass its attachments prop. Call useAttachments directly only when you manage attachments outside of CopilotChat. Requires the expo-document-picker and expo-file-system peer dependencies.
import { useAttachments } from "@copilotkit/react-native";
function useAttachments(props: UseNativeAttachmentsProps): UseNativeAttachmentsReturn;
<PropertyReference name="enabled" type="boolean" required>
Enable file attachments. When `false`, the hook is inert.
</PropertyReference>
<PropertyReference name="accept" type="string" default='"*/*"'>
MIME type filter for the picker. Supports wildcards (`"image/*"`) and
comma-separated lists (`"image/*,application/pdf"`).
</PropertyReference>
<PropertyReference name="maxSize" type="number" default="20971520">
Maximum file size in bytes. Defaults to 20 MB.
</PropertyReference>
<PropertyReference name="onUpload" type="(file: NativeFileInput) => AttachmentUploadResult | Promise<AttachmentUploadResult>">
Custom upload handler. If omitted, the file is read as base64 via
`expo-file-system` and embedded directly in the message.
</PropertyReference>
<PropertyReference name="onUploadFailed" type="(error: { reason: AttachmentUploadErrorReason; file: NativeFileInput; message: string }) => void">
Called when an attachment fails validation (e.g. wrong type or too large)
or upload.
</PropertyReference>
NativeFileInputThe React Native equivalent of the web File object.
import { useAttachments } from "@copilotkit/react-native";
import { getSourceUrl } from "@copilotkit/shared";
import { Button, Image, View } from "react-native";
function Composer() {
const { attachments, openPicker, removeAttachment } = useAttachments({
config: {
enabled: true,
accept: "image/*,application/pdf",
maxSize: 10 * 1024 * 1024,
},
});
return (
<View>
<Button title="Attach file" onPress={openPicker} />
{attachments.map((a) => (
<Image
key={a.id}
source={{ uri: getSourceUrl(a.source) }}
style={{ width: 48, height: 48 }}
/>
))}
</View>
);
}
Each Attachment exposes its content as a source (a base64 data source or a
URL source), not a ready-made URL. getSourceUrl from @copilotkit/shared
converts either form to a string you can pass to Image.
Most apps enable attachments declaratively through CopilotChat instead:
<CopilotChat agentId="default" attachments={{ enabled: true, accept: "image/*" }}>
<MyChatUI />
</CopilotChat>
CopilotChat: wires up attachments via its attachments prop and exposes openPicker / removeAttachment through useCopilotChatContext