Introduction
Copying text to the clipboard is a common feature in web apps. If you're letting your users copy coupon codes, share links, or export values with a single click. Instead of writing this logic repeatedly, why not encapsulate it in a clean and reusable custom React hook?
In this blog, we'll build a useCopy
hook from scratch, understand each part of the implementation, and see a real-world example to use it in your UI.
What Is the Clipboard API?
Modern browsers offer a Clipboard API under the navigator.clipboard
object, which allows us to:
- Programmatically read or write text
- Interact with the system clipboard securely
- Do it asynchronously
But since not all environments support it (especially older browsers or HTTP connections), we should handle fallbacks or at least warn the user.
useCopy Hook
import { useState } from 'react';
const useCopy = () => {
const [copiedText, setCopiedText] = useState();
const copy = async (text) => {
if (!navigator?.clipboard) {
console.warn('Clipboard not supported');
return false;
}
try {
await navigator.clipboard.writeText(text);
setCopiedText(text);
} catch (error) {
console.error(`Failed to copy text ${text} `, error);
setCopiedText(null);
}
};
return { copiedText, copy };
};
export default useCopy;
Now, let's understand the code step by step:
State Management
const [copiedText, setCopiedText] = useState();
We store the latest copied text so the component can display feedback (like a tooltip or success message).
Clipboard API Check
if (!navigator?.clipboard) {
console.warn('Clipboard not supported');
return false;
}
-
navigator
is a global browser object that contains info about the browser and OS. -
navigator.clipboard
is where the Clipboard API lives. - We use optional chaining (
?.
) to safely check if it exists.
Writing to the Clipboard
await navigator.clipboard.writeText(text);
setCopiedText(text);
This performs the actual copy-to-clipboard action. If it succeeds, we store the text. If it fails, we catch and log the error:
} catch (error) {
console.error(`Failed to copy text ${text} `, error);
setCopiedText(null);
}
Example Usage
Here’s how you can use useCopy
in a functional React component:
import React from 'react';
import useCopy from './useCopy';
const CopyExample = () => {
const { copiedText, copy } = useCopy();
const textToCopy = 'https://dev.to/debajit13/';
return (
<div>
<p>Click below to copy the link:</p>
<button onClick={() => copy(textToCopy)}>Copy Link</button>
{copiedText === textToCopy && <span>Text Copied Successfully!</span>}
</div>
);
};
export default CopyExample;
When you click the button, the link is copied to your clipboard. A success message is shown once copied.
Bonus: Deep dive into navigator
navigator is part of the Browser Object Model (BOM) in JavaScript. It provides useful properties and methods such as:
-
navigator.userAgent
— info about the browser -
navigator.onLine
— check if the user is online -
navigator.clipboard
— read/write access to the system clipboard
Conclusion
The useCopy
hook is a small but powerful utility that makes your app feel modern, interactive, and user-friendly. It abstracts away messy clipboard logic and gives you a clean, declarative interface for one of the most common UX features. If you liked this blog and want to learn more about Frontend Development and Software Engineering, you can follow me on Dev.
Top comments (0)