ReaJJS में, टेक्स्ट को क्लिपबोर्ड पर कॉपी कैसे करें?


147

मैं ReactJS का उपयोग कर रहा हूं और जब कोई उपयोगकर्ता किसी लिंक पर क्लिक करता है तो मैं कुछ टेक्स्ट को क्लिपबोर्ड पर कॉपी करना चाहता हूं।

मैं Chrome 52 का उपयोग कर रहा हूं और मुझे किसी अन्य ब्राउज़र का समर्थन करने की आवश्यकता नहीं है।

मैं यह नहीं देख सकता कि इस कोड का परिणाम क्लिपबोर्ड पर कॉपी किए जाने वाले डेटा में नहीं है। (कोड स्निपेट की उत्पत्ति एक रेडिट पोस्ट से है)।

क्या मैं यह गलत कर रहा हूँ? किसी को भी सुझाव है कि वहाँ एक "सही" करने के लिए क्लिपबोर्ड को copyjs का उपयोग कर लागू करने का तरीका है?

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()
}

1
क्या आपने क्लिपबोर्ड js.com या github.com/zeroclipboard/zeroclipboard की तरह तीसरे पक्ष के समाधान का उपयोग करने की कोशिश की ?
यूजोल

11
@ यूजॉल मैं वास्तव में एक और निर्भरता जोड़ने के बजाय कोड लिखना पसंद करता हूं, यह मानते हुए कि कोड काफी छोटा है।
ड्यूक डगल

इन उत्तरों की जाँच करें stackoverflow.com/questions/400212/…
elmeister

@elmeister प्रश्न अभिक्रियाओं के लिए विशिष्ट है
ड्यूक डगल

जवाबों:


180

मैं व्यक्तिगत रूप से इसके लिए पुस्तकालय की आवश्यकता नहीं देखता हूं। 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;

अद्यतन: प्रतिक्रिया में हुक का उपयोग कर फिर से लिखा 16.7.0-अल्फा.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>
  );
}

26
यह सबसे अच्छा जवाब है। जब तक कि उन्हें पुराने ब्राउज़र समर्थन की आवश्यकता न हो, तब तक हमें हर छोटी चीज़ के लिए पैकेज का उपयोग करने के लिए देवताओं को प्रोत्साहित नहीं करना चाहिए।
tugce

3
केवल रिकॉर्ड के लिए: इसके साथ एकमात्र समस्या यह है कि यदि आप पाठ को कॉपी करने की कोशिश कर रहे हैं जो पहले से ही पृष्ठ पर कुछ पाठ तत्व में नहीं है, तो आपको DOM तत्वों का एक सेट हैक करने, पाठ सेट करने, उसे कॉपी करने की आवश्यकता होगी, और इसे साफ करो। यह बहुत छोटे से कुछ के लिए कोड का एक बहुत कुछ है। आम तौर पर मैं इस बात से सहमत हूं कि देवों को लगातार पुस्तकालय स्थापित करने के लिए प्रोत्साहित नहीं किया जाना चाहिए।
क्रिस्टोफर रॉनिंग

3
इस विशेष समस्या के लिए, पाठ पहले से ही पृष्ठ पर एक तत्व में है। उस स्थिति में क्या होगा जहां उस पृष्ठ पर दृश्यमान पाठ है जिसे आप कॉपी करना चाहते हैं जो किसी तत्व में नहीं है? यह एक पूरी तरह से अलग मुद्दा है कि मैं एक समाधान दिखाने के लिए खुश हूँ। आपको प्रतिक्रिया के साथ कुछ भी हैक करने की आवश्यकता नहीं होगी, आप बस अपने रेंडर फ़ंक्शन में एक छिपा हुआ तत्व प्रदान करेंगे जो पाठ भी रखता है। तत्व तदर्थ बनाने की आवश्यकता नहीं है।
नैट

2
मुझे यह टाइपस्क्रिप्ट त्रुटि मिलती है:Property 'select' does not exist on type 'never'
एलेक्स सी

3
मुझे टाइप टाइप मिलता है: textAreaRef.current.select कोई फ़ंक्शन नहीं है
pseudozach

120

यदि आप प्रोग्राम में क्लिपबोर्ड पर डेटा लिखना चाहते हैं तो एक बटन पर इस सरल इनलाइन ऑनक्लिक फ़ंक्शन का उपयोग करें।

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

3
navigator.clipboard सभी ब्राउज़रों का समर्थन नहीं करता
प्रेमजीत

8
में 2018 प्रमुख ब्राउज़रों के लिए अपने किया गया अच्छी तरह से समर्थन लगता caniuse.com/#search=clipboard
gasolin

2
आपके द्वारा दिए गए लिंक के आधार पर, यह सफारी में पूरी तरह से समर्थित केवल अपनी तरह दिखता है ...
निब

2
मेरे usecase के लिए सबसे अच्छा काम करता है जहां कॉपी करने के लिए पाठ वास्तव में पृष्ठ पर नहीं है। धन्यवाद
NSjonas

1
आंशिक समर्थन बहुत अच्छा है, इसलिए यह अधिकांश उपयोग-मामलों के लिए पूरी तरह से समर्थित है। और जैसा कि उल्लेख किया गया है, यह सबसे अच्छा प्रोग्रामेटिक समाधान है।
Dror Bar

40

आपको निश्चित रूप से @ @ शुभम जैसे पैकेज का उपयोग करने पर विचार करना चाहिए, लेकिन मैंने आपके द्वारा बताए गए के आधार पर एक वर्किंग कोडपेन बनाया है: 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'))

3
पैकेज आपके समाधान से बेहतर क्यों है?
ड्यूक डगल सेप

6
संभावित रूप से बेहतर क्रॉस ब्राउज़र समर्थन, और बग के मामले में पैकेज पर और अधिक आँखें बग को ठीक करने की आवश्यकता है
ड्रू शस्टर

एक जादू की तरह काम करता है। हाँ। मुझे आश्चर्य है कि क्रॉस ब्राउज़र समर्थन भी है।
कार्ल पोकस

यह स्क्रीन पर एक झिलमिलाहट का कारण होगा अगर आप appendChild का उपयोग कर रहे हैं, कोई फर्क नहीं पड़ता कि कितनी जल्दी आप इसे बाद में निकाल रहे हैं?
रॉबिनन ने

1
यह अच्छा है लेकिन यह एंड्रॉइड पर क्रोम (72.0) और न ही एंड्रॉइड पर एफएफ (63.0) पर काम नहीं करता है।
कॉलिन

35

सबसे सरल तरीका react-copy-to-clipboardnpm पैकेज का उपयोग होगा ।

आप इसे निम्न आदेश के साथ स्थापित कर सकते हैं

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

यहाँ एक चलित बेला है


क्या कोई उपाय है अगर मुझे रिवर्स करने की आवश्यकता है? यानी लेखक एक ईमेल से पाठ क्षेत्र में रिएक्टज एप्लिकेशन में टेक्स्ट कॉपी करेगा। मुझे html टैग को बनाए रखने की आवश्यकता नहीं है, हालांकि, मुझे केवल लाइन ब्रेक को संरक्षित करने की आवश्यकता है।
टेकटर्टल

आपको संभवतः onpasteघटना को प्लग करने की आवश्यकता है
कोएन

यदि मैं किसी html तालिका की सामग्री को क्लिपबोर्ड पर कॉपी करना चाहता हूं तो मैं इस पैकेज का उपयोग कैसे कर सकता हूं? @ शुभम खत्री
जेन फ्रेड

19

जब आपको इस तरह से एक बटन के भीतर सब मिल सकता है तो आपको एनपीएम पैकेज की आवश्यकता क्यों है

<button 
  onClick={() =>  navigator.clipboard.writeText('Copy this text to clipboard')}
>
  Copy
</button>

मुझे उम्मीद है कि इससे @jerryurenaa को मदद मिलेगी


16

सिर्फ ईवेंट क्लिपबोर्डडैटा संग्रह विधि का उपयोग क्यों नहीं करते हैं e.clipboardData.setData(type, content)?

मेरी राय में क्लिपबोर्ड के अंदर धकेलने को प्राप्त करने के लिए सबसे कठोर तरीका है, इसे देखें (देशी प्रतिलिपि कार्रवाई करते समय डेटा को संशोधित करने के लिए इसका उपयोग किया है):

...

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

चीयर्स!

संपादित करें: परीक्षण प्रयोजनों के लिए, मैंने कोडपेन जोड़ा है: https://codepen.io/dprzygodzki/pen/ZaJMKb


3
@ कर्लपोकस प्रश्नकर्ता केवल क्रोम समाधान की तलाश में है
TechTurtle

1
Chrome संस्करण 62.0.3202.94 पर परीक्षण किया गया। यह काम कर रहा है। codepen.io/dprzygodzki/pen/ZaJMKb
डेमियन

1
@ ऑलिवरडिक्सन यह रिएक्ट इवेंट का डिफ़ॉल्ट ऑब्जेक्ट है। reactjs.org/docs/events.html
डेमियन

1
@DamianPrzygodzki मुझे इस तरह से छिपे हुए तत्वों से नफरत है, डेवलपर्स को भ्रमित करने का शानदार तरीका।
ओलिवर डिक्सन

1
@OliverDixon मैं आपको महसूस करता हूं, लेकिन मुझे लगता है कि इसका उपयोग करने के लिए अच्छा है कि कभी-कभी विधि के लिए कुछ डिफ़ॉल्ट डेटा लागू होता है, खासकर घटनाओं में।
डेमियन प्रोजोडोज़की

8

आपका कोड पूरी तरह से काम करना चाहिए, मैं इसे उसी तरह उपयोग करता हूं। केवल यह सुनिश्चित करें कि यदि क्लिक इवेंट एक बूटस्ट्रैप मोडल या कुछ जैसे पॉप अप स्क्रीन के भीतर से चालू होता है, तो बनाया गया तत्व उस मोडल के भीतर होना चाहिए अन्यथा यह कॉपी नहीं होगा। आप हमेशा उस मोडल (एक दूसरे पैरामीटर के रूप में) के भीतर एक तत्व की आईडी दे सकते हैं और इसे 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);
}

8

मैंने उपरोक्त में से कुछ के समान ही दृष्टिकोण लिया है, लेकिन इसे थोड़ा और ठोस बनाया है, मुझे लगता है। यहां, एक मूल घटक एक प्रस्ताव के रूप में यूआरएल (या जो भी पाठ आप चाहते हैं) को पारित करेगा।

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

यह उपयोगी था क्योंकि मैं Textarea के बजाय पैराग्राफ टैग चाहता था
एहसान अहमदी

धन्यवाद! केवल मुद्दा textfield छुपा रहा है
itshinkswhenitscold

3

उन लोगों के लिए जो पाठ क्षेत्र के बजाय 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)}
                        />
                    );
            }

3

यहाँ एक और उपयोग मामला है, यदि आप अपने url को वर्तमान क्लिपबोर्ड में कॉपी करना चाहते हैं:

एक विधि परिभाषित करें

const copyToClipboard = e => {
  navigator.clipboard.writeText(window.location.toString())
}

उस विधि को बुलाओ

<button copyToClipboard={shareLink}>
   Click to copy current url to clipboard
</button>

3

प्रतिक्रिया हुक के साथ सबसे अच्छा समाधान, इसके लिए बाहरी पुस्तकालयों की कोई आवश्यकता नहीं है

import React, { useState } from 'react';

const MyComponent = () => {
const [copySuccess, setCopySuccess] = useState('');

// your function to copy here

  const copyToClipBoard = async copyMe => {
    try {
      await navigator.clipboard.writeText(copyMe);
      setCopySuccess('Copied!');
    } catch (err) {
      setCopySuccess('Failed to copy!');
    }
  };

return (
 <div>
    <Button onClick={() => copyToClipBoard('some text to copy')}>
     Click here to copy
     </Button>
  // after copying see the message here
  {copySuccess}
 </div>
)
}

navigator.clip बोर्ड के बारे में और प्रलेखन के लिए यहाँ देखें , navigator.clipboard प्रलेखन navigotor.clipboard ब्राउज़र की एक बड़ी संख्या द्वारा समर्थित है यहाँ समर्थित ब्राउज़र देखो


2
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>
        )
    }
}

1

यदि आप पाठ क्षेत्र के बजाय DIV से चयन करना चाहते हैं, तो यहां कोड है। "कोड" वह मूल्य है जिसे कॉपी करना होता है

import React from 'react'
class CopyToClipboard extends React.Component {

  copyToClipboard(code) {
    var textField = document.createElement('textarea')
    textField.innerText = code
    document.body.appendChild(textField)
    textField.select()
    document.execCommand('copy')
    textField.remove()
  }
  render() {
    return (
      <div onClick={this.copyToClipboard.bind(this, code)}>
        {code}
      </div>

    )
  }
}

export default CopyToClipboard

1
एसओ का सबसे अच्छा अभ्यास एक स्पष्टीकरण के साथ अपने कोड को पूरा करना है। कृपया इसे करें।
मार्टेनकैचर

0

यहाँ मेरा कोड है:

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
<input
value={get(data, "api_key")}
styleName="input-wrap"
title={get(data, "api_key")}
ref={apikeyObjRef}
/>
  <div
onClick={() => {
  apikeyObjRef.current.select();
  if (document.execCommand("copy")) {
    document.execCommand("copy");
  }
}}
styleName="copy"
>
  复制
</div>

7
कृपया इस बात की व्याख्या जोड़ें कि यह कोड समस्या को हल कैसे करता है, बजाय केवल कोड पोस्ट करने के।
अलेक्जेंडर वान ओस्टेन्रिज

0

इसे करने का सबसे अच्छा तरीका मिला। मेरा मतलब है सबसे तेज़ तरीका: w3school

https://www.w3schools.com/howto/howto_js_copy_clipboard.asp

प्रतिक्रियाशील घटक के अंदर। हैंडल नाम से एक फंक्शन बनाएं:

function handleCopy() {
  // get the input Element ID. Save the reference into copyText
  var copyText = document.getElementById("mail")
  // select() will select all data from this input field filled  
  copyText.select()
  copyText.setSelectionRange(0, 99999)
  // execCommand() works just fine except IE 8. as w3schools mention
  document.execCommand("copy")
  // alert the copied value from text input
  alert(`Email copied: ${copyText.value} `)
}

<>
              <input
                readOnly
                type="text"
                value="exemple@email.com"
                id="mail"
              />
              <button onClick={handleCopy}>Copy email</button>

</>

यदि React का उपयोग नहीं कर रहे हैं, तो w3schools के पास टूलटिप के साथ ऐसा करने का एक अच्छा तरीका है: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_copy -clipboard2

यदि रिएक्ट का उपयोग कर रहे हैं, तो एक अच्छा विचार करें: संदेश को सचेत करने के लिए एक टोस्टिफाइ का उपयोग करें। https://github.com/fkhadra/react-toastify यह उपयोग करने के लिए बहुत आसान है। स्थापना के बाद, आप इस लाइन को बदलने में सक्षम हो सकते हैं:

 alert(`Email copied: ${copyText.value} `)

कुछ इस तरह के लिए:

toast.success(`Email Copied: ${copyText.value} `)

यदि आप इसका उपयोग करना चाहते हैं, तो इंस्टॉल टोस्टिफाइ करना न भूलें। ToastContainer और भी toss css का आयात करें:

import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"

और वापसी के अंदर टोस्ट कंटेनर जोड़ें।

import React from "react"

import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"


export default function Exemple() {
  function handleCopy() {
    var copyText = document.getElementById("mail")
    copyText.select()
    copyText.setSelectionRange(0, 99999)
    document.execCommand("copy")
    toast.success(`Hi! Now you can: ctrl+v: ${copyText.value} `)
  }

  return (
    <>
      <ToastContainer />
      <Container>
                <span>E-mail</span>
              <input
                readOnly
                type="text"
                value="myemail@exemple.com"
                id="mail"
              />
              <button onClick={handleCopy}>Copy Email</button>
      </Container>
    </>
  )
}

आपके उत्तर में केवल दूसरे संसाधन का संदर्भ होता है, लेकिन कोई विशिष्ट उत्तर नहीं। यदि w3schools सही समाधान के रूप में लिंक करते हैं, तो कृपया इसे यहां टाइप करें।
f.khantsis
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.