Я использую 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()
}
javascript
reactjs
clipboard
Герцог Дугал
источник
источник
Ответы:
Я лично не вижу необходимости в библиотеке для этого. Глядя на 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 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 Hooks в 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 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> ); }
источник
Property 'select' does not exist on type 'never'
Используйте эту простую встроенную функцию onClick для кнопки, если вы хотите программно записывать данные в буфер обмена.
onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
источник
Вам обязательно стоит подумать об использовании пакета, такого как @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'))
источник
Самый простой способ - использовать
react-copy-to-clipboard
пакет npm.Вы можете установить его с помощью следующей команды
Используйте его следующим образом.
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
Вот бегущая скрипка .
источник
onpaste
событиеЗачем вам нужен пакет npm, если вы можете получить все с помощью одной такой кнопки
<button onClick={() => navigator.clipboard.writeText('Copy this text to clipboard')} > Copy </button>
Надеюсь, это поможет @jerryurenaa
источник
Почему бы не использовать только метод сбора событий clipboardData
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
источник
Лучшее решение с перехватчиками реакции, для этого не нужны внешние библиотеки
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 navigator.clipboard поддерживает огромное количество браузеров. смотрите здесь поддерживаемый браузер.
источник
Я использовал подход, очень похожий на некоторые из вышеперечисленных, но, как мне кажется, сделал его более конкретным. Здесь родительский компонент будет передавать 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> ); };
источник
Ваш код должен работать отлично, я использую его точно так же. Только убедитесь, что если событие щелчка запускается из всплывающего окна, такого как модальное окно начальной загрузки или что-то в этом роде, созданный элемент должен находиться внутри этого модального окна, иначе он не будет копироваться. Вы всегда можете указать идентификатор элемента в этом модальном окне (в качестве второго параметра) и получить его с помощью 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); }
источник
Вот код для тех, кто пытается выбирать из 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)} /> ); }
источник
Вот еще один вариант использования, если вы хотите скопировать текущий URL в буфер обмена:
Определите метод
const copyToClipboard = e => { navigator.clipboard.writeText(window.location.toString()) }
Назовите этот метод
источник
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> ) } }
источник
Если вы хотите выбрать из 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
источник
Нашел лучший способ сделать это. я имею в виду самый быстрый способ: w3school
https://www.w3schools.com/howto/howto_js_copy_clipboard.asp
Внутри функционального компонента React. Создайте функцию с именем 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 Это очень простая в использовании библиотека. После установки вы можете изменить эту строку:
alert(`Email copied: ${copyText.value} `)
Для чего-то вроде:
toast.success(`Email Copied: ${copyText.value} `)
Если вы хотите его использовать, не забудьте установить toastify. import ToastContainer, а также всплывает css:
import { ToastContainer, toast } from "react-toastify" import "react-toastify/dist/ReactToastify.css"
и добавьте контейнер для тостов внутрь return.
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> </> ) }
источник
navigator.clipboard не работает через http-соединение в соответствии с их документом. Таким образом, вы можете проверить, идет ли он неопределенным, и вместо этого использовать document.execCommand ('copy'), это решение должно охватывать почти все браузеры.
const defaultCopySuccessMessage = 'ID copied!' const CopyItem = (props) => { const { copySuccessMessage = defaultCopySuccessMessage, value } = props const [showCopySuccess, setCopySuccess] = useState(false) function fallbackToCopy(text) { if (window.clipboardData && window.clipboardData.setData) { // IE specific code path to prevent textarea being shown while dialog is visible. return window.clipboardData.setData('Text', text) } else if (document.queryCommandSupported && document.queryCommandSupported('copy')) { const textarea = document.createElement('textarea') textarea.innerText = text // const parentElement=document.querySelector(".up-CopyItem-copy-button") const parentElement = document.getElementById('copy') if (!parentElement) { return } parentElement.appendChild(textarea) textarea.style.position = 'fixed' // Prevent scrolling to bottom of page in MS Edge. textarea.select() try { setCopySuccess(true) document.execCommand('copy') // Security exception may be thrown by some browsers. } catch (ex) { console.log('Copy to clipboard failed.', ex) return false } finally { parentElement.removeChild(textarea) } } } const copyID = () => { if (!navigator.clipboard) { fallbackToCopy(value) return } navigator.clipboard.writeText(value) setCopySuccess(true) } return showCopySuccess ? ( <p>{copySuccessMessage}</p> ) : ( <span id="copy"> <button onClick={copyID}>Copy Item </button> </span> ) }
И вы можете просто вызвать и повторно использовать компонент в любом месте, где хотите
const Sample=()=>( <CopyItem value="item-to-copy"/> )
источник
используйте эту команду, чтобы передать свое значение функции
var promise = navigator.clipboard.writeText(newClipText)
источник
вот мой код:
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
источник
<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>
источник
copyclip = (item) => { var textField = document.createElement('textarea') textField.innerText = item document.body.appendChild(textField) textField.select() document.execCommand('copy') this.setState({'copy':"Copied"}); textField.remove() setTimeout(() => { this.setState({'copy':""}); }, 1000); } <span className="cursor-pointer ml-1" onClick={()=> this.copyclip(passTextFromHere)} >Copy</span> <small>{this.state.copy}</small>
источник
Вы также можете использовать перехватчики реакции в функциональные компоненты или компоненты без состояния с помощью этого фрагмента кода: PS: Убедитесь, что вы устанавливаете useClippy через npm / yarn с помощью этой команды: npm install use-clippy или yarn add use-clippy
import React from 'react'; import useClippy from 'use-clippy'; export default function YourComponent() { // clipboard is the contents of the user's clipboard. // setClipboard('new value') wil set the contents of the user's clipboard. const [clipboard, setClipboard] = useClippy(); return ( <div> {/* Button that demonstrates reading the clipboard. */} <button onClick={() => { alert(`Your clipboard contains: ${clipboard}`); }} > Read my clipboard </button> {/* Button that demonstrates writing to the clipboard. */} <button onClick={() => { setClipboard(`Random number: ${Math.random()}`); }} > Copy something </button> </div> ); }
источник
Эта работа для меня:
const handleCopyLink = useCallback(() => { const textField = document.createElement('textarea') textField.innerText = url document.body.appendChild(textField) if (window.navigator.platform === 'iPhone') { textField.setSelectionRange(0, 99999) } else { textField.select() } document.execCommand('copy') textField.remove() toast.success('Link Copiado com sucesso') }, [url])
источник