useCopyToClipboard Hook
December 21, 2025
Copying text to the clipboard is a common feature in modern web applications — for sharing links, copying codes, or duplicating content. This hook provides a clean way to handle clipboard operations with feedback.
import { useState, useCallback } from 'react';
interface UseCopyToClipboardReturn {
copy: (text: string) => Promise<void>;
isCopied: boolean;
error: Error | null;
}
export function useCopyToClipboard(): UseCopyToClipboardReturn {
const [isCopied, setIsCopied] = useState(false);
const [error, setError] = useState<Error | null>(null);
const copy = useCallback(async (text: string) => {
try {
await navigator.clipboard.writeText(text);
setIsCopied(true);
setError(null);
// Reset after 2 seconds
setTimeout(() => setIsCopied(false), 2000);
} catch (err) {
setError(err instanceof Error ? err : new Error('Failed to copy'));
setIsCopied(false);
}
}, []);
return { copy, isCopied, error };
}
How It Works
- Uses the modern
navigator.clipboard.writeText()API. - Manages
isCopiedstate to provide user feedback. - Handles errors gracefully.
- Automatically resets the
isCopiedstate after 2 seconds.
Example Usage
function CopyButton({ text }: { text: string }) {
const { copy, isCopied, error } = useCopyToClipboard();
return (
<div>
<button onClick={() => copy(text)}>
{isCopied ? 'Copied!' : 'Copy to Clipboard'}
</button>
{error && <p className="error">Failed to copy</p>}
</div>
);
}
With Fallback for Older Browsers
export function useCopyToClipboardWithFallback(): UseCopyToClipboardReturn {
const [isCopied, setIsCopied] = useState(false);
const [error, setError] = useState<Error | null>(null);
const copy = useCallback(async (text: string) => {
try {
// Try modern API first
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(text);
} else {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
document.execCommand('copy');
textArea.remove();
}
setIsCopied(true);
setError(null);
setTimeout(() => setIsCopied(false), 2000);
} catch (err) {
setError(err instanceof Error ? err : new Error('Failed to copy'));
setIsCopied(false);
}
}, []);
return { copy, isCopied, error };
}
Use Cases
- Copy shareable links
- Copy code snippets
- Copy user IDs or tokens
- Copy formatted text
- Copy API keys or credentials
Notes
- The modern API requires a secure context (HTTPS or localhost).
- The fallback method works in older browsers but is deprecated.
- Always provide visual feedback when copying succeeds.
- Consider showing a toast notification for better UX.
A simple hook that makes clipboard operations seamless and user-friendly.