diff --git a/docs/useCopyToClipboard.md b/docs/useCopyToClipboard.md
index cc56dae1eb..f94acbc701 100644
--- a/docs/useCopyToClipboard.md
+++ b/docs/useCopyToClipboard.md
@@ -2,13 +2,23 @@
Copy text to a user's clipboard.
-
## Usage
-Basic usage
-
```jsx
const Demo = () => {
+ const [text, setText] = React.useState('');
+ const [state, copyToClipboard] = useCopyToClipboard();
+
+ return (
+
+
setText(e.target.value)} />
+
+ {state.error
+ ?
Unable to copy value: {state.error.message}
+ : state.value &&
Copied {state.value}
}
+
+ )
+
const [text, setText] = React.useState('');
const [copied, copyToClipboard] = useCopyToClipboard(text);
@@ -25,11 +35,5 @@ const Demo = () => {
## Reference
```js
-const [copied, copyToClipboard] = useCopyToClipboard(text);
-const [copied, copyToClipboard] = useCopyToClipboard(text, writeText);
+const [state, copyToClipboard] = useCopyToClipboard();
```
-
-, where
-
-- `writeText` — 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 7fcd5a7f3e..3e13b99764 100644
--- a/src/__stories__/useCopyToClipboard.story.tsx
+++ b/src/__stories__/useCopyToClipboard.story.tsx
@@ -5,19 +5,21 @@ import {useCopyToClipboard} from '..';
const Demo = () => {
const [text, setText] = React.useState('');
- const [copied, copyToClipboard] = useCopyToClipboard(text, {
- onCopy: txt => alert('success: ' + txt),
- onError: err => alert(err),
- });
+ const [state, copyToClipboard] = useCopyToClipboard();
return (
setText(e.target.value)} />
-
-
Copied: {copied ? 'Yes' : 'No'}
-
-
-
+
+ {state.error
+ ?
Unable to copy value: {state.error.message}
+ : state.value && (
+ <>
+
Copied {state.value} {state.noUserInteraction ? 'without' : 'with'} user interaction
+
+ >
+ )}
+
)
}
diff --git a/src/useCopyToClipboard.ts b/src/useCopyToClipboard.ts
index 244bcc1bfb..df00969e2a 100644
--- a/src/useCopyToClipboard.ts
+++ b/src/useCopyToClipboard.ts
@@ -1,55 +1,49 @@
-import {useState, useCallback, useRef} from 'react';
-import useUpdateEffect from './useUpdateEffect';
+import {useCallback} from 'react';
+import useSetState from './useSetState'
import useRefMounted from './useRefMounted';
-const writeTextDefault = require('copy-to-clipboard');
+import * as writeText from 'copy-to-clipboard';
-export type WriteText = (text: string) => Promise; // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
-export interface UseCopyToClipboardOptions {
- writeText?: WriteText;
- onCopy?: (text: string) => void;
- onError?: (error: any, text: string) => void;
+export interface CopyToClipboardState {
+ value?: string,
+ noUserInteraction: boolean,
+ error?: Error,
}
-export type UseCopyToClipboard = (text?: string, options?: UseCopyToClipboardOptions) => [boolean, () => void];
-
-const useCopyToClipboard: UseCopyToClipboard = (text = '', options) => {
- const {writeText = writeTextDefault, onCopy, onError} = (options || {}) as UseCopyToClipboardOptions;
-
- if (process.env.NODE_ENV !== 'production') {
- if (typeof text !== 'string') {
- console.warn('useCopyToClipboard hook expects first argument to be string.');
- }
- }
+const useCopyToClipboard = (): [CopyToClipboardState, (value: string) => void] => {
const mounted = useRefMounted();
- const latestText = useRef(text);
- const [copied, setCopied] = useState(false);
- const copyToClipboard = useCallback(async () => {
- if (latestText.current !== text) {
- if (process.env.NODE_ENV !== 'production') {
- console.warn('Trying to copy stale text.');
- }
- return;
- }
+ const [state, setState] = useSetState({
+ value: undefined,
+ error: undefined,
+ noUserInteraction: true
+ });
+ const copyToClipboard = useCallback((value) => {
try {
- await writeText(text);
+ if (process.env.NODE_ENV === 'development') {
+ if (typeof value !== "string") {
+ console.error(`Cannot copy typeof ${typeof value} to clipboard, must be a string`);
+ }
+ }
+
+ const noUserInteraction = writeText(value);
+
if (!mounted.current) return;
- setCopied(true);
- onCopy && onCopy(text);
+ setState({
+ value,
+ error: undefined,
+ noUserInteraction
+ });
} catch (error) {
if (!mounted.current) return;
- console.error(error);
- setCopied(false);
- onError && onError(error, text);
+ setState({
+ value: undefined,
+ error,
+ noUserInteraction: true
+ });
}
- }, [text]);
-
- useUpdateEffect(() => {
- setCopied(false);
- latestText.current = text;
- }, [text]);
+ }, []);
- return [copied, copyToClipboard];
+ return [state, copyToClipboard];
}
export default useCopyToClipboard;