Create copy-to-clipboard button using react-js

Create copy-to-clipboard button using react-js

By: Niraj Dhungana

Nov 29 2021

#React# copy-to-clipboard


We already have a post on how to create a copy to clipboard button with vanilla JavaScript but in this post we will create that same thing using React JS.

This is the demo which we are going to create.

If you click on this button it will copy some text to your clipboard. OMG You just copied a virus, just kidding 😜 it's just some plain text. If you use ctrl+v or paste using right click you will find out what text you just copied?


To copy text to clipboard we have an object called window.navigator. This object contains the information about browsers. Most of the major browsers support it. You can read more about it here.

I assume here you already have a React app to implement copy to clipboard demo. If not then please create one.

1npx create-react-app copy-to-clipboard-demo

Now I will create a component called CopyToClipboard. You can also create one or use a pre-existing component like an App.js.

1export default function CopyBtnDemo({ textToCopy }) {
2  return (
3    <div className="text-center my-5">
4      <button className="text-sm border w-36 border-gray-500 rounded p-2 transition">
5        Copy to clipboard
6      </button>
7    </div>
8  );

Here the code explains itself but let me explain if you feel any confusion. We have this component called CopyToClipboard. Where we are accepting a prop called textToCopy. Which we will use to copy to clipboard.

Then we are just rendering a button inside a div with some tailwind css classes. You can skip those class names if you don’t know or don’t want to use tailwind css.

Let’s add onClick listener to the button and add a new method where we can listen and handle the actual logic to copy the text.

1export default function CopyBtnDemo() {
2  const copyToClipboard = () => { };
4  return (
5    <div className="text-center my-5">
6      <button
7        onClick={copyToClipboard}>
8       ...

Here the new code is on line number 2 and line number 7.

1const copyToClipboard = () => {
2  navigator.clipboard.writeText(/* text to copy */);;

Now inside our copyToClipboard method we can use this small logic. To copy text to the clipboard. Here I am just using comment but you can use the prop which we accepted earlier.

The code above is ok if you just want to copy the text but let’s make it interesting. Let's see how we can display an alert or notify our user that they did something. Messages like copied or failed to copy.

For that I am going to change the text from inside the button and the style of the button. And if anything goes wrong I will just log it to the console.

Handling error and success

navigator.clipboard.writeText() returns a promise. So, we can use the .then() method to capture success and error both.

1const copyToClipboard = () => {
2  navigator.clipboard.writeText(textToCopy)
3	.then(/* the success method*/, /* the failed method */);

And don’t be confused here to capture both success and failed response. We can pass two methods inside the then().

Now here if the copy process is successful then I want to change the text inside that button for two second. Otherwise if anything goes wrong I want to log that to the console.

To achieve what I just told. I will add a new state inside our component called copied. And change some of the styles and text of the button if the state is true.

1const [copied, setCopied] = useState(false);
2const btnStyle = copied ? "bg-gray-500 text-white" : "";
4return (
5	<div className="text-center my-5">
6      <button
7        className={
8          btnStyle +
9          " text-sm border w-36 border-gray-500 rounded p-2 transition"
10        }
11		...
12      >
13	  {copied ? "Copied" : "Copy to clipboard"}
14     </button>

Ok this is how we can do it. Now let’s add the logic inside the .then() method which will update our copied state. According to the user's behaviour.

1const copyToClipboard = () => {
2  navigator.clipboard.writeText(textToCopy).then(
3    () => {
4      setCopied(true);
5      // changing back to default state after 2 seconds.
6      setTimeout(() => {
7        setCopied(false);
8      }, 2000);
9    },
10    (err) => {
11      console.log("failed to copy", err.mesage);
12    }

Now you have the exact thing that you saw in the demo at the beginning of this post.

Complete source code.

1// remove tailwind css classes if you don't want to use them.
2import React, { useState } from "react";
4export default function CopyBtnDemo({ textToCopy = 'Copy default' }) {
5  const [copied, setCopied] = useState(false);
7  const copyToClipboard = () => {
8    navigator.clipboard.writeText(textToCopy).then(
9      () => {
10        setCopied(true);
11        // changing back to default state after 2 seconds.
12        setTimeout(() => {
13          setCopied(false);
14        }, 2000);
15      },
16      (err) => {
17        console.log("failed to copy", err.mesage);
18      }
19    );
20  };
22  const btnStyle = copied ? "bg-gray-500 text-white" : "";
24  return (
25    <div className="text-center my-5">
26      <button
27        onClick={copyToClipboard}
28        className={
29          btnStyle +
30          " text-sm border w-36 border-gray-500 rounded p-2 transition"
31        }
32      >
33        {copied ? "Copied" : "Copy to clipboard"}
34      </button>
35    </div>
36  );

Niraj Dhungana

I hope you enjoyed reading this post and learned something new. If not then tell me how can I improve. @fsniraj