Dan Valinotti Dan is a fullstack software engineer with a primary focus on frontend development and experience building high-visibility, scalable, and accessible web applications.

Implementing copy-to-clipboard in React with Clipboard API

4 min read 1184

Implementing Copy-To-Clipboard In React With Clipboard API

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.

What is the JavaScript Clipboard API?

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 to call for both copying text to the user’s clipboard and reading items from it.

Unfortunately, not all web browsers support this API, and you can probably guess which one. It’s Internet Explorer. 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.

We made a custom demo for .
No really. Click here to check it out.

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 arguments '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.

Using Clipboard API in React

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>
  );
}

What I’ve added here is 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:

Copy Button Next To Link Being Pressed

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.

Conclusion

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. This also greatly improves the user experience on your site as well. 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, hopefully you can reap these benefits for yourself.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Dan Valinotti Dan is a fullstack software engineer with a primary focus on frontend development and experience building high-visibility, scalable, and accessible web applications.

One Reply to “Implementing copy-to-clipboard in React with Clipboard API”

Leave a Reply