问题描述
我正在尝试使用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代码和框示例。
,运行以下代码段。
- 具有一个单独的
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>
- 或者,只需在纯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>