web-dev-qa-db-fra.com

Dans reactJS, comment copier du texte dans le presse papier?

J'utilise ReactJS et lorsqu'un utilisateur clique sur un lien, je souhaite copier du texte dans le presse-papiers.

J'utilise Chrome 52 et je n'ai pas besoin de prendre en charge d'autres navigateurs.

Je ne vois pas pourquoi ce code n'entraînera pas la copie des données dans le Presse-papiers. (L'origine du fragment de code provient d'un article de Reddit).

Est-ce que je fais mal? Quelqu'un peut-il suggérer qu'il existe un moyen "correct" d'implémenter la copie dans le presse-papiers à l'aide de 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()
}
86
Duke Dougal

Personnellement, je ne vois pas le besoin d'une bibliothèque pour cela. En regardant http://caniuse.com/#feat=clipboard il est assez largement supporté maintenant, cependant vous pouvez toujours faire des choses comme vérifier pour voir si la fonctionnalité existe dans le client actuel et simplement cacher la copie bouton si ce n'est pas.

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;

Mise à jour: réécrit avec React Crochets dans React 16.7.0-alpha.0

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>
  );
}
106
Nate

Utilisez cette simple fonction onClick en ligne sur un bouton si vous souhaitez écrire des données par programme dans le Presse-papiers.

onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
36
Gary Vernon Grubb

Vous devriez absolument envisager d'utiliser un paquet tel que @Shubham ci-dessus, mais j'ai créé un codepen fonctionnel basé sur ce que vous avez décrit: http://codepen.io/dtschust/pen/WGwdVN?editors=1111 . Cela fonctionne dans mon navigateur chrome, vous pouvez peut-être voir si vous avez oublié quelque chose que j'ai fait là-bas ou si votre application présente une complexité accrue qui l'empêche de fonctionner.

// 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'))
33
Drew Schuster

Le moyen le plus simple consiste à utiliser le package react-copy-to-clipboard npm.

Vous pouvez l'installer avec la commande suivante

npm install --save react react-copy-to-clipboard

Utilisez-le de la manière suivante.

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'));

Une explication détaillée est fournie au lien suivant

https://www.npmjs.com/package/react-copy-to-clipboard

Voici une course violon .

29
Shubham Khatri

Pourquoi ne pas utiliser uniquement la méthode de collecte d'événement clipboardData e.clipboardData.setData(type, content)?

À mon avis, c’est la méthode la plus simple pour insérer du contenu dans le presse-papiers (c’est ce que j’ai utilisé pour modifier des données lors d’une copie native):

...

handleCopy = (e) => {
    e.preventDefault();
    e.clipboardData.setData('text/plain', 'Hello, world!');
}

render = () =>
    <Component
        onCopy={this.handleCopy}
    />

J'ai suivi ce chemin: https://developer.mozilla.org/en-US/docs/Web/Events/copy

À votre santé!

EDIT: À des fins de test, j'ai ajouté codepen: https://codepen.io/dprzygodzki/pen/ZaJMKb

14
Damian Przygodzki

Votre code devrait fonctionner parfaitement, je l'utilise de la même manière. Assurez-vous seulement que si l'événement click est déclenché depuis un écran contextuel tel qu'un modal bootstrap, ou quelque chose de ce genre, l'élément créé doit être dans ce modal sinon il ne sera pas copié. Vous pouvez toujours donner l'identifiant d'un élément dans ce modal (en tant que second paramètre) et le récupérer avec getElementById, puis ajouter l'élément nouvellement créé à celui-ci au lieu du document. Quelque chose comme ça:

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

J'ai adopté une approche très similaire à celle décrite ci-dessus, mais je pense que c'est un peu plus concret. Ici, un composant parent transmettra l'URL (ou le texte que vous voulez) comme accessoire.

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

Pour les personnes qui essaient de sélectionner dans la DIV plutôt que dans le champ de texte, voici le code. Le code est explicite, mais commentez ici si vous souhaitez plus d'informations:

     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)}
                        />
                    );
            }
3
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

voici mon code:

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