私はReactJSを使っていて、ユーザーがリンクをクリックしたときにテキストをクリップボードにコピーしたいのです。
Chrome 52を使用していますが、他のブラウザをサポートする必要はありません。
なぜこのコードがデータをクリップボードにコピーしないのかわかりません。 (コードスニペットの起源はRedditの投稿からのものです)。
私はこれを間違っていますか? 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()
}
私は個人的にこれのための図書館の必要性を見ません。ご覧ください 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;
更新:React 16.7.0-alpha.0のReact Hooksを使って書き直された
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 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>
);
}
あなたは間違いなく上記の@Shubhamのようなパッケージを使用することをお勧めしますが、私はあなたが説明した内容に基づいて実用的なcodepenを作成しました。 http://codepen.io/dtschust/pen/WGwdVN?editors=1111 。それは私のブラウザのクロムで動作します。おそらく、あなたが見逃したことがあったかどうか、またはこれが機能しなくなるような複雑な拡張がアプリケーションにあるかどうかを確認できます。
// 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'))
最も簡単な方法はreact-copy-to-clipboard
npmパッケージを使うことです。
次のコマンドでインストールできます
npm install --save react react-copy-to-clipboard
次のように使用してください。
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'));
詳細な説明は以下のリンクにあります。
https://www.npmjs.com/package/react-copy-to-clipboard
これが実行中の フィドル です。
プログラムでクリップボードにデータを書き込む場合は、この単純なインラインのonClick関数をボタンに使用します。
onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
なぜイベントclipboardDataコレクションメソッドe.clipboardData.setData(type, content)
だけを使わないのですか?
私の意見では、クリップボードの内側にsmthをプッシュするための最も直接的な方法です。これをチェックしてください(ネイティブコピーアクション中にデータを変更するために使用しました)。
...
handleCopy = (e) => {
e.preventDefault();
e.clipboardData.setData('text/plain', 'Hello, world!');
}
render = () =>
<Component
onCopy={this.handleCopy}
/>
私はその道をたどった: https://developer.mozilla.org/en-US/docs/Web/Events/copy
乾杯!
編集:テストの目的で、私はcodepenを追加しました: https://codepen.io/dprzygodzki/pen/ZaJMKb
あなたのコードは完璧に動作するはずです。私も同じように使っています。クリックイベントが、ブートストラップモーダルなどのポップアップ画面内から発生した場合にのみ、作成された要素がそのモーダル内になければならないことを確認してください。そうしないとコピーされません。そのモーダル内の要素のIDを(2番目のパラメータとして)常に指定して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);
}
私は上記のものと非常によく似たアプローチを取りましたが、もう少し具体的にしました。ここでは、親コンポーネントがURL(または任意のテキスト)を小道具として渡します。
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>
);
};
テキストフィールドの代わりに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)}
/>
);
}
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>
)
}
}
ここに私のコードがあります:
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