453

I'm using ReactJS and when a user clicks a link I want to copy some text to the clipboard.

I am using Chrome 52 and I do not need to support any other browsers.

I can't see why this code does not result in the data being copied to the clipboard. (the origin of the code snippet is from a Reddit post).

Am I doing this wrong? Can anyone suggest is there a "correct" way to implement copy to clipboard using reactjs?

copyToClipboard = (text) => {
  console.log('text', text)
  var textField = document.createElement('textarea')
  textField.innerText = text
  document.body.appendChild(textField)
  textField.select()
  document.execCommand('copy')
  textField.remove()
}
EugZol
  • 6,476
  • 22
  • 41
Duke Dougal
  • 24,359
  • 31
  • 91
  • 123

31 Answers31

713

Use this simple inline onClick function on a button if you want to programatically write data to the clipboard.

onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
Gary Vernon Grubb
  • 9,695
  • 1
  • 24
  • 27
  • 35
    seems its been well support for major browsers in 2018 https://caniuse.com/#search=clipboard – gasolin Oct 05 '18 at 02:33
  • 5
    based on the link you provided, it looks like its only totally supported in safari... – Nibb Apr 04 '19 at 21:15
  • 6
    works best for my usecase where to text to copy isn't actually on the page. Thanks – NSjonas May 18 '19 at 15:47
  • 1
    The partial support is very good, so it's fully supported for most use-cases. And as mentioned, this is the best programmatic solution. – Dror Bar Dec 23 '19 at 13:22
  • 1
    I was copying a `
    ...
    ` portion and this worked when other responses did not.  Thanks!
    – matsad Feb 25 '20 at 04:36
  • 1
    This works totally fine, but does someone knows how to copy to clipboard with the content being formatted ? – Mohammad Agha Nov 17 '20 at 16:42
  • 34
    Since I got stuck on this (on Chrome), `navigator.clipboard` will only work if your page is loaded from a secure origin (either HTTPS or localhost). You can check [window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts) if you need to. – aryanm Dec 31 '20 at 03:40
  • 6
    In 2021, this should be the accepted answer. Support for `navigator.clipboard` is more than universal enough. – basse Jan 14 '21 at 08:23
  • Someone knows how to remove [this](https://imgur.com/dumeWDk.png) (the ht thing) when the text copied is in \` and \`? –  Jan 26 '21 at 06:14
  • 3
    while this certainly is useful, it only works for in development as localhost or with a site w/ https. – J.E.C. Feb 25 '21 at 15:40
  • @J.E.C. You are right. Anyhow anything production grade should have https. Even in cases where security is not needed, if only to just address end user perception. – Gary Vernon Grubb Feb 26 '21 at 06:04
  • @YTG, What error? are you using HTTPs or localhost? – Gary Vernon Grubb Apr 05 '21 at 11:31
  • Using localhost. No error, just nothing is on the clipboard. – YTG Apr 07 '21 at 07:02
  • Does a console.log of whatever variable you pass to clipboard.writeText have data in it? – Gary Vernon Grubb Apr 08 '21 at 09:30
  • Note that writeText is asynchronous and returns a Promise. I think the answer should be extended by this source: https://www.w3.org/TR/clipboard-apis/#async-clipboard-api – Konrad Grzyb Aug 11 '21 at 10:13
  • 1
    Also can be used as: onClick={() => {navigator.clipboard.writeText("textString to copy")}} – heyom Feb 21 '22 at 06:14
  • How would you check for success or failed? In the case that the user denied access to clipboard or something. – kennsorr Feb 28 '23 at 20:48
  • 1
    the Clipboard API is only supported for pages served over HTTPS. How do we copy something over http? – Aayushi Apr 14 '23 at 09:25
271

I personally don't see the need for a library for this. Looking at http://caniuse.com/#feat=clipboard it's pretty widely supported now, however you can still do things like checking to see if the functionality exists in the current client and simply hide the copy button if it doesn't.

import React from 'react';

class CopyExample extends React.Component {

  constructor(props) {
    super(props);

    this.state = { copySuccess: '' }
  }

  copyToClipboard = (e) => {
    this.textArea.select();
    document.execCommand('copy');
    // This is just personal preference.
    // I prefer to not show the whole text area selected.
    e.target.focus();
    this.setState({ copySuccess: 'Copied!' });
  };

  render() {
    return (
      <div>
        {
         /* Logical shortcut for only displaying the 
            button if the copy command exists */
         document.queryCommandSupported('copy') &&
          <div>
            <button onClick={this.copyToClipboard}>Copy</button> 
            {this.state.copySuccess}
          </div>
        }
        <form>
          <textarea
            ref={(textarea) => this.textArea = textarea}
            value='Some text to copy'
          />
        </form>
      </div>
    );
  }

}
    
export default CopyExample;

Update: Rewritten using React Hooks in React 16.7.0-alpha.0

import React, { useRef, useState } from 'react';

export default function CopyExample() {

  const [copySuccess, setCopySuccess] = useState('');
  const textAreaRef = useRef(null);

  function copyToClipboard(e) {
    textAreaRef.current.select();
    document.execCommand('copy');
    // This is just personal preference.
    // I prefer to not show the whole text area selected.
    e.target.focus();
    setCopySuccess('Copied!');
  };

  return (
    <div>
      {
       /* Logical shortcut for only displaying the 
          button if the copy command exists */
       document.queryCommandSupported('copy') &&
        <div>
          <button onClick={copyToClipboard}>Copy</button> 
          {copySuccess}
        </div>
      }
      <form>
        <textarea
          ref={textAreaRef}
          value='Some text to copy'
        />
      </form>
    </div>
  );
}
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Nate
  • 6,384
  • 3
  • 25
  • 30
  • 4
    Just for the record: the only problem with this is that if you're trying to copy text that's not already in some text element on the page, you'll need to hack a set of DOM elements, set the text, copy it, and clean it up. That's alot of code for something very small. Normally I would agree that devs should not be encouraged to constantly install libraries. – Christopher Ronning May 29 '18 at 13:27
  • 3
    For this particular problem, the text is already in an element on the page. What case would there be where there's visible text on the page that you want to copy that isn't in an element? That's an entirely different issue that I'd be happy to show a solution to. You wouldn't need to hack anything with react, you'd just provide a hidden element in your render function that also holds the text. No need to create elements ad hoc. – Nate May 29 '18 at 16:40
  • Instead of 'e.targe.focus()' in case there is no event depending in how anyone might be using this, you can use the following to deselect the input/textarea: 1. For cross-browsers: window.getSelection(). 2. Problematic browsers: document.selection.empty(). More info: https://stackoverflow.com/questions/6186844/clear-a-selection-in-firefox/6187098#6187098 – rmolinamir Jan 29 '19 at 00:33
  • Adding my 2 cents to this correct answer: in some cases the position of the fake textarea matters. In my case the copy button was inside an overlay (not an iframe, but something that totally covers the page with a backgropd) and the "select" action was probably failing. Moving the textarea position inside the active page fixed the issue. – keul Mar 13 '19 at 17:16
  • 2
    I get this typescript error: `Property 'select' does not exist on type 'never'` – Alex C Mar 27 '19 at 17:40
  • 4
    I get TypeError: textAreaRef.current.select is not a function – pseudozach Oct 29 '19 at 05:16
  • im using flow-typed ```property `select` is missing in null [1]``` – gjs Apr 04 '20 at 14:42
  • 17
    This is now obsolete https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand – Benjamin Jun 22 '20 at 08:23
  • 2
    If you're getting textAreaRef.current.select is not a function, make sure your ref is actually on a – JakeD Jul 17 '20 at 02:00
  • 1
    Man, this is so refreshing after looking into overbuilt solutions like https://www.npmjs.com/package/react-copy-to-clipboard – bfeist Jan 15 '21 at 17:00
  • @Benjamin I have submitted an edit to adress `execCommand` being deprecated. It uses `navigator.clipboard.writeText` if supported and fallsback to `execCommand`. In addition, I have futher adapted this answer, and created a `withCopyText` hook for extra flexibility. Scroll way down for that answer. – Davey Dec 21 '21 at 15:03
  • I am getting `Object is possibly 'null'.` with TypeScript. – Terry Windwalker Aug 25 '22 at 08:06
132

You can get this done without the need of an external library, e.g: within a button

<button 
  onClick={() =>  navigator.clipboard.writeText('Copy this text to clipboard')}
>
  Copy
</button>

for internet explorer 11 and older browsers you might need to change the code a bit here is an example:

<button 
  onClick={() =>  window.clipboardData.setData("Text", 'Copy this text to clipboard')}>
 Copy
</button>
starball
  • 20,030
  • 7
  • 43
  • 238
jerryurenaa
  • 3,863
  • 1
  • 27
  • 17
53

You should definitely consider using a package like @Shubham above is advising, but I created a working codepen based on what you described: http://codepen.io/dtschust/pen/WGwdVN?editors=1111 . It works in my browser in chrome, perhaps you can see if there's something I did there that you missed, or if there's some extended complexity in your application that prevents this from working.

// html
<html>
  <body>
    <div id="container">

    </div>
  </body>
</html>


// js
const Hello = React.createClass({
  copyToClipboard: () => {
    var textField = document.createElement('textarea')
    textField.innerText = 'foo bar baz'
    document.body.appendChild(textField)
    textField.select()
    document.execCommand('copy')
    textField.remove()
  },
  render: function () {
    return (
      <h1 onClick={this.copyToClipboard}>Click to copy some text</h1>
    )
  }
})

ReactDOM.render(
<Hello/>,
  document.getElementById('container'))
Drew Schuster
  • 2,521
  • 12
  • 15
49

The simplest way will be use the react-copy-to-clipboard npm package.

You can install it with the following command

npm install --save react react-copy-to-clipboard

Use it in the following manner.

const App = React.createClass({
  getInitialState() {
    return {value: '', copied: false};
  },


  onChange({target: {value}}) {
    this.setState({value, copied: false});
  },


  onCopy() {
    this.setState({copied: true});
  },


  render() {
    return (
      <div>

          <input value={this.state.value} size={10} onChange={this.onChange} />

        <CopyToClipboard text={this.state.value} onCopy={this.onCopy}>
          <button>Copy</button>
        </CopyToClipboard>

                <div>
        {this.state.copied ? <span >Copied.</span> : null}
                </div>
        <br />

        <input type="text" />

      </div>
    );
  }
});

ReactDOM.render(<App />, document.getElementById('container'));

A detailed explanation is provided at the following link

https://www.npmjs.com/package/react-copy-to-clipboard

Here is a running fiddle.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Is there any solution if I need to do reverse? i.e. Author will copy text from an email to text area in reactjs application. I don't need to retain html tags, however, I need to preserve only line breaks. – TechTurtle Sep 11 '17 at 21:37
  • 1
    You probably need to plug the `onpaste` event – Koen Nov 23 '17 at 14:22
  • How can I use this package if I want to copy the contents of an html table to clipboard? @Shubham Khatri – Jane Fred Jul 10 '19 at 13:14
36

Best solution with react hooks, no need of external libraries for that

import React, { useState } from 'react';

const MyComponent = () => {
const [copySuccess, setCopySuccess] = useState('');

// your function to copy here

  const copyToClipBoard = async copyMe => {
    try {
      await navigator.clipboard.writeText(copyMe);
      setCopySuccess('Copied!');
    } catch (err) {
      setCopySuccess('Failed to copy!');
    }
  };

return (
 <div>
    <Button onClick={() => copyToClipBoard('some text to copy')}>
     Click here to copy
     </Button>
  // after copying see the message here
  {copySuccess}
 </div>
)
}

check here for further documentation about navigator.clip board , navigator.clipboard documentation navigotor.clipboard is supported by a huge number of browser look here supported browser

Jaman-Dedy
  • 567
  • 5
  • 3
33

Clipboard is well supported by major browsers in 2021. One approach would be to first build a copy to clipboard function and then call it using the onClick event handler.

function copy(text){
  navigator.clipboard.writeText(text)
}

To prevent hard coding, let's suppose the string is assigned to a variable named someText

<span onClick={() => copy(someText)}>
  {someText}
</span>
Gass
  • 7,536
  • 3
  • 37
  • 41
21

You can use event clipboardData collection method e.clipboardData.setData(type, content).

In my opinion is the most straightforward method to achieve pushing something inside the clipboard, check this out (I've used that to modify data while native copying action):

...

handleCopy = (e) => {
    e.preventDefault();
    e.clipboardData.setData('text/plain', 'Hello, world!');
}

render = () =>
    <Component
        onCopy={this.handleCopy}
    />

I followed that path: https://developer.mozilla.org/en-US/docs/Web/Events/copy

Cheers!

EDIT: For testing purposes, I've added codepen: https://codepen.io/dprzygodzki/pen/ZaJMKb

Abhinav
  • 154
  • 1
  • 5
16

I've taken a very similar approach as some of the above, but made it a little more concrete, I think. Here, a parent component will pass the url (or whatever text you want) as a prop.

import * as React from 'react'

export const CopyButton = ({ url }: any) => {
  const copyToClipboard = () => {
    const textField = document.createElement('textarea');
    textField.innerText = url;
    document.body.appendChild(textField);
    textField.select();
    document.execCommand('copy');
    textField.remove();
  };

  return (
    <button onClick={copyToClipboard}>
      Copy
    </button>
  );
};
tjgragg
  • 693
  • 1
  • 7
  • 8
10

Here's another use case, if you would like to copy the current url to your clipboard:

Define a method

const copyToClipboard = e => {
  navigator.clipboard.writeText(window.location.toString())
}

Call that method

<button copyToClipboard={shareLink}>
   Click to copy current url to clipboard
</button>
jasonleonhard
  • 12,047
  • 89
  • 66
8

Your code should work perfectly, I use it the same way. Only make sure that if the click event is triggered from within a pop up screen like a bootstrap modal or something, the created element has to be within that modal otherwise it won't copy. You could always give the id of an element within that modal (as a second parameter) and retrieve it with getElementById, then append the newly created element to that one instead of the document. Something like this:

copyToClipboard = (text, elementId) => {
  const textField = document.createElement('textarea');
  textField.innerText = text;
  const parentElement = document.getElementById(elementId);
  parentElement.appendChild(textField);
  textField.select();
  document.execCommand('copy');
  parentElement.removeChild(textField);
}
Kupi
  • 903
  • 1
  • 10
  • 16
8

No need to install third party packages. I try to keep it as simple as possible. This worked well for me.

import React, { useState } from "react"    
function MyApp() {
    const [copySuccess, setCopySuccess] = useState(null);
    const copyToClipBoard = async copyMe => {
       try {
           await navigator.clipboard.writeText(copyMe);
           setCopySuccess('Copied!');
       } 
       catch (err) {
           setCopySuccess('Failed to copy!');
       }
    };
     
    return (
        <button onClick={(e) => copyToClipBoard(what you want to copy goes here)} >
           My button
        </button>    
       )
    }
Jobajuba
  • 836
  • 7
  • 16
7

This work for me:

const handleCopyLink = useCallback(() => {
    const textField = document.createElement('textarea')
    textField.innerText = url
    document.body.appendChild(textField)
    if (window.navigator.platform === 'iPhone') {
      textField.setSelectionRange(0, 99999)
    } else {
      textField.select()
    }
    document.execCommand('copy')
    textField.remove()
  }, [url])
6

The plain simple answer will be

navigator.clipboard.writeText("value")

Bhuwan Panta
  • 61
  • 1
  • 2
6

Fully working React component using Material UI

For a better understanding, I've prepared a CodeSandbox as well. Hope that helps.

import { useState } from "react";
import { IconButton, Snackbar } from "@mui/material";
import ShareIcon from "@mui/icons-material/Share";

const CopyToClipboardButton = () => {
  const [open, setOpen] = useState(false);

  const handleClick = () => {
    setOpen(true);
    navigator.clipboard.writeText(window.location.toString());
  };

  return (
    <>
      <IconButton onClick={handleClick} color="primary">
        <ShareIcon />
      </IconButton>
      <Snackbar
        message="Copied to clibboard"
        anchorOrigin={{ vertical: "top", horizontal: "center" }}
        autoHideDuration={20000}
        onClose={() => setOpen(false)}
        open={open}
      />
    </>
  );
};

export default CopyToClipboardButton;

Here's what the button looks like:

enter image description here

And when you click it:

enter image description here

Source: https://fwuensche.medium.com/react-button-to-copy-to-clipboard-75ef5ecdc708

Flavio Wuensche
  • 9,460
  • 1
  • 57
  • 54
6

first create BTN then add this onClick:

onClick={() =>  navigator.clipboard.writeText(textState)}

or

onClick={() =>  navigator.clipboard.writeText('Your text for copy')}
Sky
  • 291
  • 4
  • 5
4

use this command to pass your value to the function

var promise = navigator.clipboard.writeText(newClipText)
tomnyson
  • 189
  • 2
  • 7
3

For those people who are trying to select from the DIV instead of the text field, here is the code. The code is self-explanatory but comment here if you want more information:

     import React from 'react';
     ....

    //set ref to your div
          setRef = (ref) => {
            // debugger; //eslint-disable-line
            this.dialogRef = ref;
          };

          createMarkeup = content => ({
            __html: content,
          });

    //following function select and copy data to the clipboard from the selected Div. 
   //Please note that it is only tested in chrome but compatibility for other browsers can be easily done

          copyDataToClipboard = () => {
            try {
              const range = document.createRange();
              const selection = window.getSelection();
              range.selectNodeContents(this.dialogRef);
              selection.removeAllRanges();
              selection.addRange(range);
              document.execCommand('copy');
              this.showNotification('Macro copied successfully.', 'info');
              this.props.closeMacroWindow();
            } catch (err) {
              // console.log(err); //eslint-disable-line
              //alert('Macro copy failed.');
            }
          };

              render() {
                    return (
                        <div
                          id="macroDiv"
                          ref={(el) => {
                            this.dialogRef = el;
                          }}
                          // className={classes.paper}
                          dangerouslySetInnerHTML={this.createMarkeup(this.props.content)}
                        />
                    );
            }
connect2Coder
  • 1,122
  • 1
  • 13
  • 25
3

navigator.clipboard doesn't work over http connection according to their document. So you can check if it's coming undefined and use document.execCommand('copy') instead, this solution should cover almost all the browsers

const defaultCopySuccessMessage = 'ID copied!'

const CopyItem = (props) => {
  const { copySuccessMessage = defaultCopySuccessMessage, value } = props

  const [showCopySuccess, setCopySuccess] = useState(false)


  function fallbackToCopy(text) {
    if (window.clipboardData && window.clipboardData.setData) {
      // IE specific code path to prevent textarea being shown while dialog is visible.
      return window.clipboardData.setData('Text', text)
    } else if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
      const textarea = document.createElement('textarea')
      textarea.innerText = text
      // const parentElement=document.querySelector(".up-CopyItem-copy-button")
      const parentElement = document.getElementById('copy')
      if (!parentElement) {
        return
      }
      parentElement.appendChild(textarea)
      textarea.style.position = 'fixed' // Prevent scrolling to bottom of page in MS Edge.
      textarea.select()
      try {
        setCopySuccess(true)
        document.execCommand('copy') // Security exception may be thrown by some browsers.
      } catch (ex) {
        console.log('Copy to clipboard failed.', ex)
        return false
      } finally {
        parentElement.removeChild(textarea)
      }
    }
  }

  const copyID = () => {
    if (!navigator.clipboard) {
      fallbackToCopy(value)
      return
    }
    navigator.clipboard.writeText(value)
    setCopySuccess(true)
  }

  return showCopySuccess ? (
    <p>{copySuccessMessage}</p>
  ) : (
    <span id="copy">
      <button onClick={copyID}>Copy Item </button>
    </span>
  )
}

And you can just call and reuse the component anywhere you'd like to

const Sample=()=>(
   <CopyItem value="item-to-copy"/>
)
Ugur Yilmaz
  • 469
  • 6
  • 17
2
import React, { Component } from 'react';

export default class CopyTextOnClick extends Component {
    copyText = () => {
        this.refs.input.select();

        document.execCommand('copy');

        return false;
    }

    render () {
        const { text } = this.state;

        return (
            <button onClick={ this.copyText }>
                { text }

                <input
                    ref="input"
                    type="text"
                    defaultValue={ text }
                    style={{ position: 'fixed', top: '-1000px' }} />
            </button>
        )
    }
}
Yash Pokar
  • 4,939
  • 1
  • 12
  • 25
1

If you want to select from the DIV instead of the text field, here is the code. The "code" is the value that has to be copied

import React from 'react'
class CopyToClipboard extends React.Component {

  copyToClipboard(code) {
    var textField = document.createElement('textarea')
    textField.innerText = code
    document.body.appendChild(textField)
    textField.select()
    document.execCommand('copy')
    textField.remove()
  }
  render() {
    return (
      <div onClick={this.copyToClipboard.bind(this, code)}>
        {code}
      </div>

    )
  }
}

export default CopyToClipboard
Haris George
  • 291
  • 5
  • 16
1

Found best way to do it. i mean the fastest way: w3school

https://www.w3schools.com/howto/howto_js_copy_clipboard.asp

Inside a react functional component. Create a function named handleCopy:

function handleCopy() {
  // get the input Element ID. Save the reference into copyText
  var copyText = document.getElementById("mail")
  // select() will select all data from this input field filled  
  copyText.select()
  copyText.setSelectionRange(0, 99999)
  // execCommand() works just fine except IE 8. as w3schools mention
  document.execCommand("copy")
  // alert the copied value from text input
  alert(`Email copied: ${copyText.value} `)
}

<>
              <input
                readOnly
                type="text"
                value="exemple@email.com"
                id="mail"
              />
              <button onClick={handleCopy}>Copy email</button>

</>

If not using React, w3schools also have one cool way to do this with tooltip included: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard2

If using React, a cool think to do: Use a Toastify to alert the message. https://github.com/fkhadra/react-toastify This is the lib very easy to use. After installation, you may be able to change this line:

 alert(`Email copied: ${copyText.value} `)

For something like:

toast.success(`Email Copied: ${copyText.value} `)

If you want to use it, dont forget to Install toastify. import ToastContainer and also toasts css:

import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"

and add the toast container inside return.

import React from "react"

import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"


export default function Exemple() {
  function handleCopy() {
    var copyText = document.getElementById("mail")
    copyText.select()
    copyText.setSelectionRange(0, 99999)
    document.execCommand("copy")
    toast.success(`Hi! Now you can: ctrl+v: ${copyText.value} `)
  }

  return (
    <>
      <ToastContainer />
      <Container>
                <span>E-mail</span>
              <input
                readOnly
                type="text"
                value="myemail@exemple.com"
                id="mail"
              />
              <button onClick={handleCopy}>Copy Email</button>
      </Container>
    </>
  )
}
Iago Barreto
  • 103
  • 1
  • 11
  • Your answer only contains the reference to another resource, but no specific answer. If the w3schools link as the correct solution, please type it up here. – f.khantsis Mar 26 '20 at 12:54
1
 copyclip = (item) => {
    var textField = document.createElement('textarea')
    textField.innerText = item
    document.body.appendChild(textField)
    textField.select()
    document.execCommand('copy')
    this.setState({'copy':"Copied"});
    textField.remove()
    setTimeout(() => {
      this.setState({'copy':""});
    }, 1000);
 }

 <span   className="cursor-pointer ml-1" onClick={()=> this.copyclip(passTextFromHere)} >Copy</span> <small>{this.state.copy}</small>
manoj patel
  • 1,150
  • 12
  • 10
1

You can also use react hooks into function components or stateless components with this piece of code: PS: Make sure you install useClippy through npm/yarn with this command: npm install use-clippy or yarn add use-clippy

import React from 'react';
import useClippy from 'use-clippy';

export default function YourComponent() {

// clipboard is the contents of the user's clipboard.
  // setClipboard('new value') wil set the contents of the user's clipboard.

  const [clipboard, setClipboard] = useClippy();

  return (
    <div>

      {/* Button that demonstrates reading the clipboard. */}
      <button
        onClick={() => {
          alert(`Your clipboard contains: ${clipboard}`);
        }}
      >
        Read my clipboard
      </button>

      {/* Button that demonstrates writing to the clipboard. */}
      <button
        onClick={() => {
          setClipboard(`Random number: ${Math.random()}`);
        }}
      >
        Copy something
      </button>
    </div>
  );
}
Blessing
  • 2,450
  • 15
  • 22
1
const handleCopy = async () => {
    let copyText = document.getElementById('input') as HTMLInputElement;
    copyText.select();
    document.execCommand('copy');
  };

return (
  <TextField
     variant="outlined"
     value={copyText}
     id="input" 
  />
);

This is work for me.

Thilanka
  • 53
  • 7
1
make a componant as follows :- 

//react functional componant 

import React, { useState } from "react";

function CopyToClipboard(props) {
  const [copied, setCopied] = useState("copy");
  return (
    <div
      className="font-medium mr-4 text-green-700 cursor-pointer"
      onClick={() => {
        navigator.clipboard.writeText(props.text);
        setCopied("copied");
      }}>
      {copied}
    </div>
  );
}

export default CopyToClipboard;

//then use this componant anywhere

<CopyToClipboard text={"text you want to copy"}></CopyToClipboard>

//it will give a text saying "copy"`enter code here` and after clicking on that text, text provided with props will get copied
                    
                  
Maverick
  • 21
  • 3
0

here is my code:

import React from 'react'

class CopyToClipboard extends React.Component {

  textArea: any

  copyClipBoard = () => {
    this.textArea.select()
    document.execCommand('copy')
  }

  render() {
    return (
      <>
        <input style={{display: 'none'}} value="TEXT TO COPY!!" type="text" ref={(textarea) => this.textArea = textarea}  />
        <div onClick={this.copyClipBoard}>
        CLICK
        </div>
      </>

    )
  }
}

export default CopyToClipboard
Alan
  • 9,167
  • 4
  • 52
  • 70
0
<input
value={get(data, "api_key")}
styleName="input-wrap"
title={get(data, "api_key")}
ref={apikeyObjRef}
/>
  <div
onClick={() => {
  apikeyObjRef.current.select();
  if (document.execCommand("copy")) {
    document.execCommand("copy");
  }
}}
styleName="copy"
>
  复制
</div>
camille
  • 16,432
  • 18
  • 38
  • 60
bob
  • 11
0

you can use useRef to select text inside an element then copy it to clipboard

import React, { useRef } from "react";

const Comp = () => {
   const copyTxt = useRef();

   const handleCopyTxt = () => {
   let txtDiv = copyTxt.current;
      if (document.selection) {
        // IE
        var range = document.body.createTextRange();
        range.moveToElementText(txtDiv);
        range.select();
      } else if (window.getSelection) {
        // other browsers
        var range = document.createRange();
        range.selectNode(txtDiv);
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
      }
      document.execCommand("copy");
    }

    return ( <div ref={copyTxt} > some text to copied </div> )
}
0

Inspired by @nate 's answer I have created a withCopyText react hook. And, added navigator.clipboard.writeText support with execCommand fallback.

The hook means that it can be reused across many components without repeating code. See the example component CopyText for implementation.

import React, { useRef, useState } from 'react';

const withCopyText = (textElementRef) => {
  if (!textElementRef) throw 'withCopyText: ref is required';

  const [copyStatus, setCopyStatus] = useState('');
  const [support, setSupport] = useState({
    navigatorClipboard: !!navigator.clipboard,
    exec: !!document.queryCommandSupported('copy'),
  });

  const copyToClipboard = (e) => {
    if ('' !== copyStatus) {
      setCopyStatus('');
      await new Promise((resolve) => setTimeout(resolve, 200));
    }

    // clipboard.writeText has wide but not 100% support
    // https://caniuse.com/?search=writeText
    if (support.navigatorClipboard) {
      try {
        navigator.clipboard.writeText(textElementRef.current.value);
        return setCopyStatus('success');
      } catch (e) {
        setSupport({ ...support, navigatorClipboard: false });
      }
    }
    // execCommand has > 97% support but is deprecated, use it as a fallback
    // https://caniuse.com/?search=execCommand
    // https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
    if (!support.navigatorClipboard) {
      try {
        textElementRef.current.select();
        document.execCommand('copy');
        e.target.focus();
        setCopyStatus('success');
      } catch (e) {
        setSupport({ ...support, exec: false });
        return setCopyStatus('fail');
      }
    }
  };

  return {
    copyStatus,
    copyToClipboard,
    support: Object.values(support).includes(true),
  };
};

const CopyText = ({ text }) => {
  const textElementRef = useRef(null);

  const { copyStatus, copyToClipboard, support } = withCopyText(textElementRef);

  return (
    <span>
      {support && <button onClick={copyToClipboard}>Copy</button>}
      {'success' === copyStatus && <span>Copied to clipboard!</span>}
      {'fail' === copyStatus && <span>Sorry, copy to clipboard failed</span>}
      <input type="text" ref={textElementRef} value={text} readOnly={true} />
    </span>
  );
};

export { CopyText, withCopyText };

Davey
  • 2,355
  • 1
  • 17
  • 18
0

For React Developers

 const preventCopyPasteBody = (state) => {
       document.addEventListener(state, (evt) => {
      if (evt.target.id === 'body') {
             evt.preventDefault();
           return false;
          }
        return false;
       }, false);
      }

 preventCopyPasteBody ("contextmenu")
 preventCopyPasteBody ("copy")
 preventCopyPasteBody ("paste")
 preventCopyPasteBody ("cut")

<Typography id="body" variant="body1"  component="div" className={classes.text} style={{ fontSize: fontSize }}>{story}</Typography>
Shahnad S
  • 983
  • 10
  • 17