Skip to content

Commit 1586963

Browse files
committed
Add successDuration option for success message.
This fixes #4.
1 parent 7613d11 commit 1586963

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,23 @@ function App() {
3636
}
3737
```
3838
39+
You can reset the `isCopied` value after a certain amount of time with the `successDuration` option.
40+
41+
```jsx
42+
import useClipboard from "react-use-clipboard";
43+
44+
function App() {
45+
const [isCopied, setCopied] = useClipboard("Text to copy", {
46+
// `isCopied` will go back to `false` after 1000ms.
47+
successDuration: 1000
48+
});
49+
50+
return (
51+
<button onClick={setCopied}>
52+
Was it copied? {isCopied ? "Yes! 👍" : "Nope! 👎"}
53+
</button>
54+
);
55+
}
56+
```
57+
3958
This package only works in versions of React that support Hooks.

src/index.test.tsx

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from "react";
2-
import { cleanup, fireEvent, render } from "@testing-library/react";
2+
import { cleanup, fireEvent, render, act } from "@testing-library/react";
33
import useClipboard from "./";
44

55
afterEach(cleanup);
@@ -24,3 +24,71 @@ test("display sucess message if the copy worked", () => {
2424

2525
expect(button.textContent).toBe("Yes");
2626
});
27+
28+
describe("successDuration", () => {
29+
test("`isCopied` becomes false after `successDuration` time ellapses", () => {
30+
jest.useFakeTimers();
31+
const successDuration = 1000;
32+
33+
const Component = () => {
34+
const [isCopied, setCopied] = useClipboard("Text to copy", {
35+
successDuration
36+
});
37+
38+
return (
39+
<button onClick={setCopied} data-testid="btn-example">
40+
{isCopied ? "Yes" : "Nope"}
41+
</button>
42+
);
43+
};
44+
45+
const { getByTestId } = render(<Component />);
46+
const button = getByTestId("btn-example");
47+
48+
expect(button.textContent).toBe("Nope");
49+
50+
fireEvent.click(button);
51+
52+
expect(button.textContent).toBe("Yes");
53+
54+
// Fast-forward half-way
55+
jest.advanceTimersByTime(successDuration / 2);
56+
57+
expect(button.textContent).toBe("Yes");
58+
59+
act(() => {
60+
// Go to the end
61+
jest.advanceTimersByTime(successDuration / 2);
62+
});
63+
64+
expect(button.textContent).toBe("Nope");
65+
});
66+
67+
test("`isCopied` is always true if `successDuration` is not provided", () => {
68+
jest.useFakeTimers();
69+
70+
const Component = () => {
71+
const [isCopied, setCopied] = useClipboard("Text to copy", {});
72+
73+
return (
74+
<button onClick={setCopied} data-testid="btn-example">
75+
{isCopied ? "Yes" : "Nope"}
76+
</button>
77+
);
78+
};
79+
80+
const { getByTestId } = render(<Component />);
81+
const button = getByTestId("btn-example");
82+
83+
expect(button.textContent).toBe("Nope");
84+
85+
fireEvent.click(button);
86+
87+
expect(button.textContent).toBe("Yes");
88+
89+
// Fast-forward half-way
90+
jest.runAllTimers();
91+
92+
expect(button.textContent).toBe("Yes");
93+
});
94+
});

src/index.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
1-
import { useState } from "react";
1+
import { useState, useEffect } from "react";
22
import copy from "copy-to-clipboard";
33

4-
export default function useCopyClipboard(text: string): [boolean, () => void] {
4+
interface IOptions {
5+
/**
6+
* Reset the status after a certain number of milliseconds. This is useful
7+
* for showing a temporary success message.
8+
*/
9+
successDuration?: number;
10+
}
11+
12+
export default function useCopyClipboard(
13+
text: string,
14+
options?: IOptions
15+
): [boolean, () => void] {
516
const [isCopied, setIsCopied] = useState(false);
17+
const successDuration = options && options.successDuration;
18+
19+
useEffect(() => {
20+
if (isCopied && successDuration) {
21+
const id = setTimeout(() => {
22+
setIsCopied(false);
23+
}, successDuration);
24+
25+
return () => {
26+
clearTimeout(id);
27+
};
28+
}
29+
}, [isCopied, successDuration]);
630

731
return [
832
isCopied,

0 commit comments

Comments
 (0)