I'm using ReactJS and when a user clicks a link I want to copy some text to the clipboard.
我正在使用ReactJS,当用户点击链接时,我想将一些文本复制到剪贴板。
I am using Chrome 52 and I do not need to support any other browsers.
我使用的是Chrome 52,我不需要支持任何其他浏览器。
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).
我不明白为什么这段代码不会导致数据被复制到剪贴板。 (代码片段的来源是Reddit帖子)。
Am I doing this wrong? Can anyone suggest is there a "correct" way to implement copy to clipboard using reactjs?
我做错了吗?任何人都可以建议使用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()
}
7 个解决方案
#1
28
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.
我个人认为不需要图书馆。看看http://caniuse.com/#feat=clipboard现在它得到了广泛的支持,但你仍然可以做一些事情,比如查看当前客户端中是否存在该功能,如果不存在则只需隐藏复制按钮。
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 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;
#2
22
The simplest way will be use the react-copy-to-clipboard
npm package.
最简单的方法是使用react-copy-to-clipboard npm包。
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.
这是一个奔跑的小提琴。
#3
20
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.
你应该考虑使用像上面的@Shubham这样的软件包建议,但我根据你描述的内容创建了一个有效的代码:http://codepen.io/dtschust/pen/WGwdVN?edit = 1111。它可以在我的浏览器中使用chrome,也许你可以看到我在那里做过你错过的东西,或者你的应用程序中是否有一些扩展的复杂性阻止了它的工作。
// 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'))
#4
8
Why do not use just event clipboardData collection method e.clipboardData.setData(type, content)
?
为什么不使用事件clipboardData集合方法e.clipboardData.setData(type,content)?
In my opinion is the most streightforward method to achieve pushing smth inside clipboard, check this out (i've used that to modify data while native copying action):
在我看来是实现在剪贴板中推送smth的最直接的方法,检查一下(我用它来修改数据,同时进行本机复制操作):
...
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
我遵循了这条道路: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
编辑:为了测试目的,我添加了codepen:https://codepen.io/dprzygodzki/pen/ZaJMKb
#5
4
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:
你的代码应该完美运行,我以同样的方式使用它。只有确保如果在弹出屏幕内触发click事件(如bootstrap模式或其他内容),创建的元素必须在该模式内,否则不会复制。您总是可以在该模态中给出元素的id(作为第二个参数)并使用getElementById检索它,然后将新创建的元素追加到该文件而不是文档。像这样的东西:
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);
}
#6
0
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:
对于那些试图从DIV而不是文本字段中选择的人来说,这里是代码。代码是不言自明的,但如果您想了解更多信息,请在此处进行评论:
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)}
/>
);
}
#7
0
Use this simple inline onClick function on a button if you want to programatically write data to the clipboard.
如果要以编程方式将数据写入剪贴板,请在按钮上使用此简单的内联onClick函数。
onClick={() => {navigator.clipboard.writeText(this.state.codeToCopy)}}
It was rightly pointed out that navigator.clipboard is not supported by all browsers yet. Until then your best bet is this answer
正确地指出,所有浏览器都不支持navigator.clipboard。在此之前,你最好的选择是这个答案
#1
28
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.
我个人认为不需要图书馆。看看http://caniuse.com/#feat=clipboard现在它得到了广泛的支持,但你仍然可以做一些事情,比如查看当前客户端中是否存在该功能,如果不存在则只需隐藏复制按钮。
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 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;
#2
22
The simplest way will be use the react-copy-to-clipboard
npm package.
最简单的方法是使用react-copy-to-clipboard npm包。
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.
这是一个奔跑的小提琴。
#3
20
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.
你应该考虑使用像上面的@Shubham这样的软件包建议,但我根据你描述的内容创建了一个有效的代码:http://codepen.io/dtschust/pen/WGwdVN?edit = 1111。它可以在我的浏览器中使用chrome,也许你可以看到我在那里做过你错过的东西,或者你的应用程序中是否有一些扩展的复杂性阻止了它的工作。
// 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'))
#4
8
Why do not use just event clipboardData collection method e.clipboardData.setData(type, content)
?
为什么不使用事件clipboardData集合方法e.clipboardData.setData(type,content)?
In my opinion is the most streightforward method to achieve pushing smth inside clipboard, check this out (i've used that to modify data while native copying action):
在我看来是实现在剪贴板中推送smth的最直接的方法,检查一下(我用它来修改数据,同时进行本机复制操作):
...
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
我遵循了这条道路: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
编辑:为了测试目的,我添加了codepen:https://codepen.io/dprzygodzki/pen/ZaJMKb
#5
4
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:
你的代码应该完美运行,我以同样的方式使用它。只有确保如果在弹出屏幕内触发click事件(如bootstrap模式或其他内容),创建的元素必须在该模式内,否则不会复制。您总是可以在该模态中给出元素的id(作为第二个参数)并使用getElementById检索它,然后将新创建的元素追加到该文件而不是文档。像这样的东西:
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);
}
#6
0
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:
对于那些试图从DIV而不是文本字段中选择的人来说,这里是代码。代码是不言自明的,但如果您想了解更多信息,请在此处进行评论:
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)}
/>
);
}
#7
0
Use this simple inline onClick function on a button if you want to programatically write data to the clipboard.
如果要以编程方式将数据写入剪贴板,请在按钮上使用此简单的内联onClick函数。
onClick={() => {navigator.clipboard.writeText(this.state.codeToCopy)}}
It was rightly pointed out that navigator.clipboard is not supported by all browsers yet. Until then your best bet is this answer
正确地指出,所有浏览器都不支持navigator.clipboard。在此之前,你最好的选择是这个答案