diff --git a/README.md b/README.md index 74449a3cc6..7b4f10b2bb 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ - [**Side-effects**](./docs/Side-effects.md) - [`useAsync`](./docs/useAsync.md) — resolves an `async` function. - [`useAsyncRetry`](./docs/useAsyncRetry.md) — `useAsync` with `retry()` method. + - [`useCopyToClipboard`](./docs/useCopyToClipboard.md) — copies text to clipboard. - [`useDebounce`](./docs/useDebounce.md) — debounces a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usedebounce--demo) - [`useFavicon`](./docs/useFavicon.md) — sets favicon of the page. - [`useLocalStorage`](./docs/useLocalStorage.md) — manages a value in `localStorage`. diff --git a/docs/useCopyToClipboard.md b/docs/useCopyToClipboard.md index ce59f7dc4e..79b83f7b4a 100644 --- a/docs/useCopyToClipboard.md +++ b/docs/useCopyToClipboard.md @@ -1,54 +1,35 @@ # `useCopyToClipboard` -copy text to a users clipboard. +Copy text to a user's clipboard. -## Usage - -### basic usage: - -```jsx -import {useCopyToClipboard} from 'react-use'; -const myComp = (props) => { - const [success, copyToClipboard] = useCopyToClipboard(); - const myText = 'text to be copied'; - return ( - copyToClipboard(myText) }>{myText} - ) -} -``` +## Usage -### with timeout: +Basic usage ```jsx -import {useCopyToClipboard} from 'react-use'; +const Demo = () => { + const [text, setText] = React.useState(''); + const [copied, copyToClipboard] = useCopyToClipboard(text); -const myComp = (props) => { - const [success, copyToClipboard] = useCopyToClipboard(2000); - const myText = 'text to be copied'; return (
- copyToClipboard(myText) }>{myText} - { success && copied to clipboard} + setText(e.target.value)} /> + +
Copied: {copied ? 'Yes' : 'No'}
- ) + ) } ``` -### with custom polyfill: +## Reference -```jsx -import {useCopyToClipboard} from 'react-use'; -import * as clipboard from "clipboard-polyfill" - -const myComp = (props) => { - const [success, copyToClipboard] = useCopyToClipboard(undefined, clipboard.writeText); - const myText = 'text to be copied'; - return ( -
- copyToClipboard(myText) }>{myText} - { success && copied to clipboard} -
- ) -} +```js +const [copied, copyToClipboard] = useCopyToClipboard(text); +const [copied, copyToClipboard] = useCopyToClipboard(text, copyFunction); ``` + +, where + +- `copyFunction` — function that receives a single string argument, which + it copies to user's clipboard. diff --git a/src/__stories__/useCopyToClipboard.story.tsx b/src/__stories__/useCopyToClipboard.story.tsx index d97437e53e..fa346a017f 100644 --- a/src/__stories__/useCopyToClipboard.story.tsx +++ b/src/__stories__/useCopyToClipboard.story.tsx @@ -4,13 +4,14 @@ import ShowDocs from './util/ShowDocs'; import {useCopyToClipboard} from '..'; const Demo = () => { - const [success, copyToClipboard] = useCopyToClipboard(2000); - const textToCopy = "text to be copied" + const [text, setText] = React.useState(''); + const [copied, copyToClipboard] = useCopyToClipboard(text); + return (
- {textToCopy} - - { success && text copied!} + setText(e.target.value)} /> + +
Copied: {copied ? 'Yes' : 'No'}
@@ -18,6 +19,6 @@ const Demo = () => { ) } -storiesOf('UI|useCopyToClipboard', module) +storiesOf('Side-effects|useCopyToClipboard', module) .add('Docs', () => ) .add('Demo', () => ) diff --git a/src/useCopyToClipboard.ts b/src/useCopyToClipboard.ts index 01d7457b37..0515f9270f 100644 --- a/src/useCopyToClipboard.ts +++ b/src/useCopyToClipboard.ts @@ -1,41 +1,27 @@ -import {useState, useEffect} from 'react'; -import * as clipboard from "clipboard-polyfill" +import useUpdateEffect from './useUpdateEffect'; +import {useState, useCallback} from 'react'; const copyDefault = (text) => { - console.log('run'); - const element = document.createElement('textarea'); // create textarea HTML element - element.value = text; // add the text to be copied to the element - document.body.appendChild(element); // add element to DOM - element.select(); // select the text - document.execCommand('copy'); // execute copy command - document.body.removeChild(element); // remove element from DOM + const element = document.createElement('textarea'); + element.value = text; + document.body.appendChild(element); + element.select(); + document.execCommand('copy'); + document.body.removeChild(element); }; +const useCopyToClipboard = (text: string = '', copy = copyDefault): [boolean, () => void] => { + const [copied, setCopied] = useState(false); + const copyToClipboard = useCallback(() => { + copy(text); + setCopied(true); + }, [text]); -const useCopyToClipboard = (timeout = undefined, copy = copyDefault) => { + useUpdateEffect(() => { + setCopied(false); + }, [text]); - const [success, setSuccess] = useState(false); - - const copyToClipboard = (text) => { - - if (typeof text == "string" || typeof text == "number" ) { - copy(text); - setSuccess(true); - } - else { - setSuccess(false); - console.error(`Cannot copy typeof ${typeof text} to clipboard, must be a valid string or number.`); - } - } - - useEffect( () => { - // if timeout given, set success to false - if (timeout) { - if (success) setTimeout( () => setSuccess(false), timeout); - } - }, [success]) - - return [success, copyToClipboard]; + return [copied, copyToClipboard]; } export default useCopyToClipboard;