A couple of days ago I implemented a feature to allow viewers on my website to easily copy code blocks on my website. Personally, it is quite a useful feature
for a technical blog.
In this article, I'm going to share how you can implement the same for your sites - applicable to all React-based sites.
useCopyableRef
hook
Thanks to React hook functionality, I've encapsulated the logic into an easily understandable and reusable hook:
import { useRef, useState } from "react";
import copyToClipboard from "copy-to-clipboard"; // You'll need this package: `yarn add copy-to-clipboard`.
const useCopyableRef = <T extends HTMLElement = HTMLElement>(
delay: number = 4 * SECONDS // You may want to change this to 4000, or define SECONDS somewhere in your application.
) => {
const ref = useRef<T>(null);
const [isCopied, setCopied] = useState(false);
const copy = () => {
if (isCopied) return;
if (!ref.current) throw new Error("Ref is nil.");
copyToClipboard(ref.current.textContent || "");
setCopied(true);
setTimeout(() => setCopied(false), delay);
};
return { ref, isCopied, copy };
};
export default useCopyableRef;
It's simple, right?
Usage in UI components
useCopyableRef
is similar to useRef
, additionally, it returns isCopied
and copy
props, which you'd need to implement your UI components.
Implementing your UI components can be as simple as the following example:
import useCopyableRef from "~/hooks/useCopyableRef";
const CodeBlock = (props: React.HTMLProps<HTMLPreElement>) => {
const { ref, isCopied, copy } = useCopyableRef<HTMLPreElement>();
return (
<>
<pre ref={ref} {...props} />
<button onClick={copy} disabled={isCopied}>
{isCopied ? "Copied!" : "Copy"}
</button>
</>
);
};
export default CodeBlock;
That's it, don't forget to style your components however you want to!
Top comments (0)