web-dev-qa-db-ja.com

reactJSで、クリップボードにテキストをコピーする方法?

私は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()
}
73
Duke Dougal

私は個人的にこれのための図書館の必要性を見ません。ご覧ください 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>
  );
}
95
Nate

あなたは間違いなく上記の@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'))
31
Drew Schuster

最も簡単な方法は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

これが実行中の フィドル です。

29
Shubham Khatri

プログラムでクリップボードにデータを書き込む場合は、この単純なインラインのonClick関数をボタンに使用します。

onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
24

なぜイベント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

13

あなたのコードは完璧に動作するはずです。私も同じように使っています。クリックイベントが、ブートストラップモーダルなどのポップアップ画面内から発生した場合にのみ、作成された要素がそのモーダル内になければならないことを確認してください。そうしないとコピーされません。そのモーダル内の要素の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);
}
7
Kupi

私は上記のものと非常によく似たアプローチを取りましたが、もう少し具体的にしました。ここでは、親コンポーネントが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>
  );
};
4
tjgragg

テキストフィールドの代わりに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)}
                        />
                    );
            }
2
connect2Coder
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>
        )
    }
}
2
Yash Pokar

ここに私のコードがあります:

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
0
Alan