Which package to install
| Package | Use when | Expo Go | Images |
|---|---|---|---|
expo-clipboard | Expo apps (managed or dev build) | Yes | Yes |
@react-native-clipboard/clipboard | Bare React Native without Expo modules | No | Partial |
Clipboard from 'react-native' | Nothing: removed from core | - | - |
Old tutorials import Clipboard from react-native. That export was deprecated and then removed, so the import fails on current versions. For an Expo app, the answer is expo-clipboard:
npx expo install expo-clipboardA copy button that tells the user it worked
import { useEffect, useRef, useState } from 'react';
import { Pressable, Text } from 'react-native';
import * as Clipboard from 'expo-clipboard';
import * as Haptics from 'expo-haptics';
export function CopyButton({ value, label = 'Copy' }: { value: string; label?: string }) {
const [copied, setCopied] = useState(false);
const timer = useRef<ReturnType<typeof setTimeout>>();
useEffect(() => () => clearTimeout(timer.current), []);
const copy = async () => {
await Clipboard.setStringAsync(value);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
setCopied(true);
clearTimeout(timer.current);
timer.current = setTimeout(() => setCopied(false), 2000);
};
return (
<Pressable
onPress={copy}
accessibilityRole="button"
accessibilityLabel={copied ? 'Copied' : `${label} ${value}`}
hitSlop={8}
>
<Text style={{ color: '#fb923c', fontWeight: '600' }}>{copied ? 'Copied' : label}</Text>
</Pressable>
);
}Copying is invisible, so the label swap and a light haptic are what make it feel like it worked. The timer is cleared on unmount so leaving the screen within two seconds does not set state on an unmounted component. Android 13 and later also show a small system confirmation when an app copies, so on those phones keep your own feedback subtle rather than adding a second toast. If you want a toast anyway, the toast guide has a lightweight one.
Reading the clipboard without the iOS paste prompt
Since iOS 16, when an app reads the clipboard from code, iOS asks the user “Allow Paste?”. An app that reads on launch to sniff for a promo code shows that prompt every time it opens, which looks suspicious. Three rules avoid it:
- Check with
hasStringAsync()first. It reports whether text exists without reading it, so no prompt. Use it to decide whether to show a Paste button. - Only call
getStringAsync()when the user taps your Paste button. The prompt can still appear, but it now makes sense to the user. - On iOS, use
ClipboardPasteButtonfrom expo-clipboard. It renders the system paste button, and because the user tapped a system control, iOS hands over the content with no prompt.
const [canPaste, setCanPaste] = useState(false);
useEffect(() => {
Clipboard.hasStringAsync().then(setCanPaste);
}, []);
const paste = async () => {
const text = await Clipboard.getStringAsync();
const code = text.trim().toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 8);
setPromoCode(code);
};Treat clipboard content as untrusted input: trim it, strip characters your field does not accept, and cap the length. People paste whole sentences, trailing newlines, and things they copied hours ago.
Images and listening for changes
setImageAsync(base64) copies an image, and getImageAsync({ format: 'png' }) returns the clipboard image with a data URI you can pass straight to an Image. To get a base64 string from a file on disk, read it with expo-file-system.
addClipboardListener fires when the clipboard changes while your app is in the foreground. It tells you the content type, not the content, so it does not trigger the paste prompt. Remove the listener in your effect cleanup.
Copy or share?
Copy is right for short values the user will paste somewhere specific: codes, addresses, IDs. When the goal is to send something to a person, the share sheet is one tap shorter, and it already includes Copy as an option.
Small touches like a copy button with feedback are easy to forget when you are focused on the main feature. Describe the screen to ShipNative and it generates them as real React Native with expo-clipboard, ready to try on your phone in Expo Go.