If you’re reading this blog post, there’s a very good chance you’ve probably cloned a git repository from GitHub. One of the small but mighty features GitHub added to its site allows users to click a button to copy the Git URL to your clipboard so that you can easily paste it into your terminal to clone the repository to your local machine.
This is a lot easier than having to select the entire line of text, then click Control+C or Command+C to copy it. It also prevents you from missing any characters of the URL when you select it.
Now, let’s say you’re building a new blog website for yourself and you want to make it as easy as possible for readers to share a post with someone. Some social media sites offer ways to use a link and automatically start a new post on their site, but not every app supports that kind of functionality.
What if you want to copy a URL and send it to someone over Zoom or iMessage? It would greatly improve the user experience if we gave users a button to copy the text. It would also be especially helpful for mobile users.
In this post, I’m going to show you how to accomplish this by creating a reusable React component that will accept the text as a prop value, and, on click, will copy the text to the user’s clipboard.
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
Thankfully, in the age of modern web development, we’re afforded many useful web APIs that make tasks like copying and pasting text in the browser easy. The current de-facto API for clipboard interaction is the Clipboard API, which provides a few simple functions you can use for both copying text to the user’s clipboard and reading items from it.
Unfortunately, not all web browsers support this API as of the time of writing. While some browsers fully or partially support it, Internet Explorer doesn’t support it at all.

However, there is a legacy function you can use as a backup if you still have to support IE, using document.execCommand('copy').
Here is an example of a function that accepts text as an argument and copies it to the user’s clipboard:
export async function copyTextToClipboard(text) {
if ('clipboard' in navigator) {
return await navigator.clipboard.writeText(text);
} else {
return document.execCommand('copy', true, text);
}
}
Now, let’s walk through this.
First, we have an asynchronous function called copyTextToClipboard, which has a single argument text. It checks if the property clipboard exists on the navigator object. This is an easy way to check if the current browser supports the Clipboard API.
Next, if the browser supports the Clipboard API, we wait for the promise navigator.clipboard.writeText(text) to be resolved and return it.
Otherwise, we call the Document.execCommand function with the argument 'copy', true, text. You can read about the arguments of this command in the MDN Docs.
When you run this command in a browser, it will copy whatever text is passed in as a parameter to the user’s clipboard, so that when the user pastes the text, it will appear.
Now that we have a simple working function for this, we’re going to implement it into a flexible React component.
Let’s start by setting up a simple React component that visually represents what we’re trying to achieve:
function ClipboardCopy({ copyText }) {
const [isCopied, setIsCopied] = useState(false);
// TODO: Implement copy to clipboard functionality
return (
<div>
<input type="text" value={copyText} readOnly />
<button>
<span>{isCopied ? 'Copied!' : 'Copy'}</span>
</button>
</div>
);
}
Here, I’ve set up the component ClipboardCopy, which accepts the property copyText. This will be the text that we want our users to have copied. It will render a read-only <input> element that displays our copyText string and a button that we’ll use to execute our copy function.
I’ve also added the state value isCopied to keep track of whether the text has been copied to the clipboard and change the text shown on our copy button.
Now, we need to create an onClick handler function for our button that will asynchronously call our copyToClipboard function and pass copyText, as an argument.
Based on the result of the function, we will either change the state of isCopied to true, or, if an error occurs, we’ll print it to the console. If the command is successful, the next time the user pastes text on their device, the value of copyText will be the result.
function ClipboardCopy({ copyText }) {
const [isCopied, setIsCopied] = useState(false);
// This is the function we wrote earlier
async function copyTextToClipboard(text) {
if ('clipboard' in navigator) {
return await navigator.clipboard.writeText(text);
} else {
return document.execCommand('copy', true, text);
}
}
// onClick handler function for the copy button
const handleCopyClick = () => {
// Asynchronously call copyTextToClipboard
copyTextToClipboard(copyText)
.then(() => {
// If successful, update the isCopied state value
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, 1500);
})
.catch((err) => {
console.log(err);
});
}
return (
<div>
<input type="text" value={copyText} readOnly />
{/* Bind our handler function to the onClick button property */}
<button onClick={handleCopyClick}>
<span>{isCopied ? 'Copied!' : 'Copy'}</span>
</button>
</div>
);
}
I’ve added a new function, handleCopyClick, which serves as the onClick event handler for our button element.
When the user clicks the button, the event handler function is executed, and our asynchronous function copyTextToClipboard is executed.
Once the function is resolved, it either sets the isCopied state value to true or, if an error occurs, prints the error.
I’ve also added a setTimeout function that resets the copied state value back to false after 1.5 seconds. This allows us to give the user some interaction feedback because copying text to a clipboard is a “background task” that doesn’t provide any inherent feedback.
Now, we can use this component anywhere in our React app, like so:
function App() {
return (
<div className="App">
<ClipboardCopy copyText="https://google.com" />
<ClipboardCopy copyText="https://logrocket.com" />
</div>
);
}
Finally, when you run the app, this is what your user should see:

You can improve this solution by providing better feedback in the case of an error in calling copyTextToClipboard. If you have an error component in your project, you could call a function or change the state to display an error to the user, rather than print text to the console that the user will most likely never see.
Don’t want to manually write the component that implements the copy and reading to clipboard functionality? Well, there are open-source alternatives that you can use. Let’s check some of them out.
React-copy-to-clipboard is a React component that allows you to copy text to your clipboard. It’s based on the JavaScript copy-to-clipboard npm package which, unlike our previous example, uses the experimental ClipboardData API, which is supported in most browsers.

It’s also straightforward to use. First, you’ll need to install the component by running npm install react-copy-to-clipboard on your terminal. Now you can use the component, as shown below:
import "./styles.css";
import { CopyToClipboard } from "react-copy-to-clipboard";
export default function App() {
return (
<div className="App">
<h1>Clipboard Copy</h1>
<CopyToClipboard
text="text"
onCopy={() => alert("Copied")}>
<span>Copy to clipboard with span</span>
</CopyToClipboard>
</div>
);
}
The component accepts a text and an onCopy prop. The text prop allows you to set the text you intend to copy, while the onCopy prop is an event that fires when a copy activity is carried out successfully. In our example, we use the native JavaScript alert. In a real application, use something that is less intrusive, like Snackbar.
useCopy React HookuseCopy is a React Hook that lets you copy text into your user’s clipboard. It uses the copy-to-clipboard JavaScript library we discussed earlier, which means it does not use the Clipboard API. Instead, it uses the Clipboard Data API.
Implementation is smooth, just the way you’d normally use React Hooks. Install the plugin by running npm install useCopy on your terminal, import the useCopy Hook and use it like so:
import React from "react";
import useCopy from "use-copy";
export default function App() {
const [copied, copy, setCopied] = useCopy("https://logrocket.com, this is the text to copy");
const copyText = () => {
copy();
setTimeout(() => {
setCopied(false);
}, 3000);
};
return (
<div>
{copied ? "Copied to clipboard" : <a onClick={copyText}>Copy text</a>}
</div>
);
}
By default, the copied state variable is set to false until the copy function is called. Then, we can reset the status back to false after three seconds to allow the user to copy again.
It might also interest you to see how we implement this library. I’ve extracted the code from the project’s GitHub repository so you can see how elegant it is:
import copyToClipboard from 'copy-to-clipboard';
import { useState, useRef, useEffect, useCallback } from 'react';
export default function useCopy(str: string): [boolean, () => void, (value: boolean) => void] {
const copyableString = useRef(str);
const [copied, setCopied] = useState(false);
const copyAction = useCallback(() => {
const copiedString = copyToClipboard(copyableString.current);
setCopied(copiedString);
}, [copyableString]);
useEffect(() => {
copyableString.current = str;
}, [str]);
return [copied, copyAction, setCopied];
}
Now that we’ve covered the JavaScript Clipboard API, you can see how easy it is to implement it into whatever your use case is, or even consider a third-party library if you choose. This improves the user experience in your application, and, of course, making it simple for users to share your content can also increase your site exposure if you are trying to gain an audience for your content. After reading this, I hope you can reap these benefits for yourself!
Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
server-side
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>

line-clamp to trim lines of textMaster the CSS line-clamp property. Learn how to truncate text lines, ensure cross-browser compatibility, and avoid hidden UX pitfalls when designing modern web layouts.

Discover seven custom React Hooks that will simplify your web development process and make you a faster, better, more efficient developer.

Promise.all still relevant in 2025?In 2025, async JavaScript looks very different. With tools like Promise.any, Promise.allSettled, and Array.fromAsync, many developers wonder if Promise.all is still worth it. The short answer is yes — but only if you know when and why to use it.

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the October 29th issue.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now
One Reply to "Implementing copy-to-clipboard in React with Clipboard API"
Wow Daniel, I appreciate how well you explained everything! Maureen Jones