reactJS에서 텍스트를 클립 보드에 복사하는 방법은 무엇입니까?


147

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

1
clipboardjs.com 또는 github.com/zeroclipboard/zeroclipboard 와 같은 타사 솔루션을 사용해 보셨습니까 ?
EugZol

11
@EugZol 코드가 상당히 작다고 가정하면 다른 종속성을 추가하는 대신 코드를 작성하는 것이 좋습니다.
Duke Dougal

이 답변을 확인하십시오 stackoverflow.com/questions/400212/…
elmeister

@elmeister 문제는 reactjs에 고유 한
듀크 두글

답변:


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;

업데이트 : 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>
  );
}

26
이것이 가장 좋은 대답입니다. 우리는 개발자들이 오래된 브라우저 지원이 필요하지 않은 한 모든 작은 일에 패키지를 사용하도록 권장해서는 안됩니다.
tugce

3
레코드의 경우 :이 문제의 유일한 문제는 페이지의 일부 텍스트 요소에없는 텍스트를 복사하려는 경우 DOM 요소 집합을 해킹하고 텍스트를 설정하고 복사해야한다는 것입니다. 청소하십시오. 그것은 아주 작은 것을위한 많은 코드입니다. 일반적으로 개발자가 지속적으로 라이브러리를 설치하도록 권장해서는 안된다는 데 동의합니다.
Christopher Ronning

3
이 특정 문제의 경우 텍스트가 이미 페이지의 요소에 있습니다. 페이지에 복사하려는 텍스트에 요소가 아닌 텍스트가 보이는 경우는 무엇입니까? 그것은 해결책을 보여줄 수있는 완전히 다른 문제입니다. 반응으로 아무것도 해킹 할 필요가 없으며 렌더링 기능에 텍스트를 포함하는 숨겨진 요소 만 제공하면됩니다. 임시 요소를 만들 필요가 없습니다.
Nate

2
이 타이프 스크립트 오류가 발생합니다.Property 'select' does not exist on type 'never'
Alex C

3
나는 TypeError를 얻는다 : textAreaRef.current.select는 함수가 아니다
pseudozach

120

프로그래밍 방식으로 데이터를 클립 보드에 쓰려면 버튼에이 간단한 인라인 onClick 함수를 사용하십시오.

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

3
navigator.clipboard는 모든 브라우저를 지원하지 않습니다
Premjeet

8
2018 년 주요 브라우저에 대한되어 잘 지원을 보인다 caniuse.com/#search=clipboard
gasolin

2
당신이 제공 한 링크를 바탕으로, 그것은 사파리에서만 완전히 지원되는 것처럼 보입니다 ...
Nibb

2
복사 할 텍스트가 실제로 페이지에없는 유스 케이스에 가장 적합합니다. 감사합니다
NSjonas

1
부분적 지원은 매우 우수하므로 대부분의 사용 사례에서 완벽하게 지원됩니다. 언급 한 바와 같이, 이것이 최고의 프로그래밍 솔루션입니다.
Dror Bar

40

위의 @Shubham과 같은 패키지를 사용하는 것이 좋습니다.하지만 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
솔루션보다 패키지가 더 나은 이유는 무엇입니까?
Duke Dougal

6
잠재적으로 더 나은 크로스 브라우저 지원 및 버그 수정이 필요한 경우 패키지에 대한 더 많은 관심
Drew Schuster

매력처럼 작동합니다. 예. 크로스 브라우저 지원에 대해서도 궁금합니다.
Karl Pokus

appendChild를 사용하고 있기 때문에 나중에 얼마나 빨리 제거하더라도 화면에서 깜박임이 발생합니까?
robinnnnn

1
이것은 좋지만 Android의 Chrome (72.0) 또는 Android의 FF (63.0)에서는 작동하지 않습니다.
colin

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

여기는 바이올린을 실행 합니다.


되돌려 야 할 경우 해결책이 있습니까? 즉, Author는 reactjs 애플리케이션의 이메일에서 텍스트 영역으로 텍스트를 복사합니다. html 태그를 유지할 필요는 없지만 줄 바꿈 만 유지해야합니다.
TechTurtle

아마도 onpaste이벤트 를 연결해야 할 것입니다.
Koen

html 테이블의 내용을 클립 보드에 복사하려면이 패키지를 어떻게 사용합니까? @Shubham Khatri
Jane Fred

19

이처럼 하나의 버튼 안에 모든 것을 얻을 수있을 때 왜 npm 패키지가 필요합니까?

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

이것이 @jerryurenaa에 도움이되기를 바랍니다.


16

이벤트 클립 보드 만 사용하지 않는 이유 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

건배!

편집 : 테스트 목적으로 코드 펜을 추가했습니다 : https://codepen.io/dprzygodzki/pen/ZaJMKb


3
@KarlPokus 질문자는 Chrome 솔루션 만 찾고 있습니다
TechTurtle

1
Chrome 버전 62.0.3202.94에서 테스트되었습니다. 작동 중입니다. codepen.io/dprzygodzki/pen/ZaJMKb
Damian Przygodzki

1
@OliverDixon React 이벤트의 기본 객체입니다. reactjs.org/docs/events.html
Damian Przygodzki

1
@DamianPrzygodzki 나는 이와 같은 숨겨진 요소를 싫어하여 개발자를 혼란스럽게합니다.
올리버 딕슨

1
@OliverDixon 나는 당신을 느낍니다. 그러나 때로는 이벤트, 특히 이벤트에서 메소드에 적용되는 일부 기본 데이터가 있다는 것을 알게되는 것이 좋습니다.
Damian Przygodzki

8

코드가 완벽하게 작동해야합니다. 동일한 방식으로 사용합니다. 부트 스트랩 모달과 같은 팝업 화면에서 클릭 이벤트가 트리거되는 경우 생성 된 요소가 해당 모달 내에 있어야합니다. 그렇지 않으면 복사되지 않습니다. 항상 해당 모달 내의 요소 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);
}

8

나는 위의 일부와 매우 유사한 접근 방식을 취했지만 조금 더 구체적으로 만들었습니다. 여기서 상위 컴포넌트는 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>
  );
};

이것은 Textarea
Ehsan Ahmadi

감사! 만 문제는 텍스트 필드 숨어
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
SO의 모범 사례는 설명과 함께 코드를 완성하는 것입니다. 제발
MartenCatcher

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
코드를 게시하는 대신이 코드로 문제를 해결하는 방법에 대한 설명을 추가하십시오.
Alexander van Oostenrijk

0

가장 좋은 방법을 찾았습니다. 나는 가장 빠른 방법을 의미 : w3school

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

반응 기능 구성 요소 내부. handleCopy라는 함수를 작성하십시오.

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

React를 사용하는 경우 다음과 같이하십시오. Toastify를 사용하여 메시지를 경고하십시오. https://github.com/fkhadra/react-toastify 이것은 매우 사용하기 쉬운 lib입니다. 설치 후 다음 줄을 변경할 수 있습니다.

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

같은 :

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

그것을 사용하려면 toastify를 설치하는 것을 잊지 마십시오. ToastContainer를 가져오고 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.