Search code examples
javascriptreactjsreact-hooksuse-ref

How to copy HTML to clipboard using react hooks?


I have a section that has a table now I want the user to be able to copy the HTML code of the table to the clipboard.

Here is my solution on code sandbox : live demo

Js code below

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

export default function App() {
  const tableRef = useRef(null);
  const [copySuccess, setCopySuccess] = useState("");

  const copyToClipboard = (e) => {
    const code =tableRef.current.innerHTML;
    console.log('code', code);
    document.execCommand("copy");
    e.target.focus();
    setCopySuccess("Copied!");
  };

  return (
    <div className="App">
      <div ref={tableRef} className="table">
        <table>
          <thead>
            <tr>
              <th>#</th>
              <th>First Name</th>
              <th>Last Name</th>
              <th>Username</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>1</td>
              <td>Mark</td>
              <td>Otto</td>
              <td>@mdo</td>
            </tr>
          </tbody>
        </table>
      </div>

      {document.queryCommandSupported("copy") && (
        <div>
          <button onClick={copyToClipboard}>Copy</button>
          {copySuccess}
        </div>
      )}
    </div>
  );
}

Unfortunately, this is not copying the HTML code.

What do I need to change to be able to copy HTML to the clipboard.?

What is wrong here?


Solution

  • The problem is it copies selected/highlighted text to the clipboard so you just need to do that programmatically before running execCommand.

    1. Add a hidden input (set invisible and position absolute/off-screen)
    2. In copy function, set the value of that input to the html
    3. select the hidden input with the select event
    4. execCommand(‘copy’);

    EDIT

    It might work with an input type of hidden or setting display: none; but I vaguely remember this blocking the select event when I did this a few years back.