How to Copy to Clipboard in React

Code blocks and text inputs are great ways to show and interact with data, but they often fall short for giving visitors an easy way to copy what’s inside. Using the Clipboard API, we can easily set up a copy action to give our visitors a better user experience.

Table of Contents

YouTube Preview
View on YouTube

Copying to Clipboard using the Clipboard API

The Clipboard API is a browser-native way of interacting with a visitors clipboard.

It includes both the ability to read what’s already in a visitors clipboard (somewhat similar to a paste action) as well as the ability to write new data (similar to a copy action).

While some parts of this API have limited support, it’s pretty well supported on most modern browsers at the time of writing this.

Copying text in React

To copy text, we can use the writeText method available on navigator.clipboard.

await navigator.clipboard.writeText('My Text');

writeText returns a promise, so we want to await that command.

Copying image data in React

The Clipboard API also supports copying image data as a PNG (as well as text or HTML) by using the write method.

We can copy image data by creating a new instance of ClipboardItem from a Blob and passing it to the write method.

const data = [new ClipboardItem({ ['image/png']: blob })];
await navigator.clipboard.write(data);

The above assumes the data Blob data being written is a PNG, where you need to ensure you pass in the appropriate type for the Blob.

If you’re looking to get a Blob from an existing image URL, you can first download the image, obtain the content type and the Blob, and then construct your ClipboardItem.

const response = await fetch('https://res.cloudinary.com/spacejelly-tutorials/image/upload/v1704743747/my-clipboard/Windows_11_Clippy_paperclip_emoji_rlnfod.png');
const contentType = response.headers.get('Content-Type');
const blob = await response.blob();

const data = [new ClipboardItem({ [contentType]: blob })];
await navigator.clipboard.write(data);

Fallback options for older browsers

The writeText and write methods both have the best support out of the Clipboard API methods, particularly writeText which is pretty well supported throughout all modern browsers, but given it’s still relatively new in web API terms, if you need to support older browsers, you may want to provide a fallback.

The execCommand method is one way to achieve this, though its considered a deprecated API.

You would first need to “select” the text such as text inside of an input then execute the copy command:

document.querySelector('#my-input').select();
document.execCommand('copy');

If trying to provide backwards compatibility though, you may want to consider using a library that handles this for you which can provide even more support, such as react-copy-to-clipboard or the library that react-copy-to-clipboard uses which is copy-to-clipboard.

For instance, if using copy-to-clipboard, you can copy text by running:

import copy from 'copy-to-clipboard';
copy('My Text');

You can even use the Clipboard API when supported with a fallback in browsers its not with:

if ( 'clipboard' in navigator ) {
  await navigator.clipboard.writeText('My Text')
} else {
  copy('My Text');
}

Reading from Clipboard with the Clipboard API

While writing to clipboard is likely a much more common need, the Clipboard API also gives us access to the readText and read methods to grab the top value from a visitors keyboard.

This isn’t without security considerations though, as a visitor must explicitly permit access to their Clipboard before it being read.

These are also the two methods that have the least browser support, where they are not supported in Firefox at the time of writing this.

Reading text from Clipboard in React

To read text, we can invoke the readText method:

const text = await navigator.clipboard.readText();

Once your visitor permits this action, the text value will now be stored in the text constant from the example above.

Reading image data from Clipboard in React

Reading image data from a Clipboard is a little bit more involved than text using the read method. Similar to write, read supports image data as a PNG, HTML, and text, but in our example we’ll be using image data.

The first step is to read the data.

const clipboard = await navigator.clipboard.read();

After the visitor provides permission and the Clipboard is read, we’ll end up with an array of ClipboardItems where we can then access the data based on type.

const image = await clipboard[0].getType('image/png');

In this instance, I’m grabbing the first ClipboardItem and getting the data by its type image/png.

To read all the data copied, you can loop through the ClipboardItems.

const images = await Promise.all(clipboard.map(clipboardItem => {
  return clipboardItem.getType('image/png');
}));

getType returns a promise which is why we use Promise.all to await for all images to be read. This is also assuming that each image is a PNG, where to validate the item is a PNG before trying to read it, you can first inspect the ClipboardItem’s types property.

const images = await Promise.all(clipboard.map(clipboardItem => {
  if ( !clipboardItem.types.includes('image/png') ) return;
  return clipboardItem.getType('image/png');
}));

Adding Convenience for a Better Experience

While most devices should support the ability to copy values from a browser, giving visitors a way to easily copy text or data with a button or action just gives them a smoother experience when trying to interact with your app.

When implementing copy UIs, consider adding confirmation notifications, such as a little green checkmark on success, or letting them know if its failed.

The best experiences will provide convenient ways to interact while ensure your visitor gets feedback from their actions.