使用useRef挂钩将副本复制到剪贴板

问题描述

我正在尝试使用useRef钩子处理到React中的复制到剪贴板。没有任何其他库,如何实现它?这是我的代码,但是会引发错误“ myRef.current.select不是函数”。

import React,{ useRef } from "react";

const Element = () => {
  const myRef = useRef();

  const copyToClipboard = () => {
    myRef.current.select();
    document.execCommand("copy");
  };

  return (
    <div>
      <span onClick={copyToClipboard} ref={myRef}>
        Text to be copied
      </span>
    </div>
  );
};

export default Element;

解决方法

看看this solution,我只是将其调整为适合您的用例。

  const copyToClipboard = () => {
    const range = document.createRange();
    range.selectNode(myRef.current);
    window.getSelection().addRange(range);

    try {
      // Now that we've selected the anchor text,execute the copy command
      const successful = document.execCommand('copy');
      const msg = successful ? 'successful' : 'unsuccessful';
      console.log('Copy email command was ' + msg);
    } catch(err) {
      console.log('Oops,unable to copy');
    }

    // Remove the selections - NOTE: Should use
    // removeRange(range) when it is supported
    window.getSelection().removeAllRanges();
  };
,

Ciao,我找到了一个解决方案,但我不得不使用input而不是span。而且我没有使用useRef钩子,而只是使用了一个变量(let myInput = null;),然后在输入ref上写了ref={(ref) => myInput = ref}。这样,您的copyToClipboard就可以正常工作。

代码:

function App() {
  let myInput = null;
  const copyToClipboard = () => {
    myInput.select();
    document.execCommand("copy");
    alert("Copied the text: " + myInput.value);
  };

  return (
    <div>
      <input readOnly value="Text to copy" onClick={copyToClipboard} ref={(ref) => myInput = ref} />
    </div>
  );
}

Here代码和框示例。

,

运行以下代码段。

  1. 具有一个单独的CopyToClipElement组件(带有React Hooks),该组件处理给定文本prop的副本。在渲染器中使用此组件。

const CopyToClipElement = ({ text }) => {
  const myRef = React.useRef(null);
  const [data,setData] = React.useState(text);
  React.useEffect(() => setData(text),[text]);

  React.useEffect(() => {
    if (myRef.current && data) {
      myRef.current.select();
      document.execCommand("copy");
      setData(null);
    }
  },[data,myRef.current]);

  return <div>{data && <textarea ref={myRef}>{data}</textarea>}</div>;
};

const Element = () => {
  const [copyText,setCopyText] = React.useState("");
  const data = ["Text to be copied","Copy foo"];

  return (
    <div>
      {data.map((text) => (
        <span
          style={{ margin: "10px",cursor: "pointer",color: 'blue' }}
          onClick={() => setCopyText(text)}
        >
          {text}
        </span>
      ))}
      <CopyToClipElement text={copyText} />
    </div>
  );
};

const domContainer = document.querySelector('#app');
ReactDOM.render(<Element/>,domContainer);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

<div id="app"> </div>

  1. 或者,只需在纯JS中添加实用程序方法copyToClipboard

const copyToClipboard = (text: string) => {
  const ta = document.createElement("textarea");
  ta.innerText = text;
  document.body.appendChild(ta);
  ta.select();
  document.execCommand("copy");
  ta.remove();
};

const Element = () => {
  const data = ["Text to be copied","Copy Bar"];

  return (
    <div>
      {data.map((text) => (
        <span
          style={{ margin: "10px",color: 'red' }}
          onClick={() => copyToClipboard(text)}
        >
          {text}
        </span>
      ))}
    </div>
  );
};

const domContainer = document.querySelector('#app');
ReactDOM.render(<Element />,domContainer);
    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

    <div id="app"> </div>