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

6 min read 1683

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

browser support for clipboard API
Source: MDN

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.

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.


More great articles from LogRocket:


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:

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.

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.

Alternative ways to copy text to clipboard in React

React-copy-to-clipboard

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.

copy clipboard react third-party library browser compatibility

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 Hook

useCopy 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];
}

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, 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!

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 and mobile 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