Posted on • Originally published atbionicjulia.com on
Creating a Copy to Clipboard Button in React
I'm currently working on a social sharing module that I can place at the bottom of my React app screens. The idea is to allow visitors to share my link on their socials with a quick click of a social icon. In addition to the usual suspects of Facebook, Twitter and Instagram, I also wanted to include a "copy to clipboard" option for visitors that didn't necessarily want to post directly on a social platform. Here's a step by step on how I created a...
Copy to clipboard button
My end goal was to have a component comprising an icon and text that reads "Copy link". Upon clicking on the component, the text should change to "Copied" and blink for a couple of seconds, before reverting back to "Copy link".
Step 1 - Javascript logic
I had no idea how to effect a copy to clipboard action in Javascript before starting this build. Turns out it's not that hard, but you have to do it in a slightly roundabout way. Essentially, what's happening is that you need to:
- Create an
input
element in the DOM and set a value for it; - Append the
input
element to the document body, which then allows you to select it; - Run the
copy
command so that the value is now copied to clipboard; and - Remove this temporary
input
element you've just been created, from the DOM.
functioncopyToClipboard(){consttempInput=document.createElement('input');tempInput.value='https://bionicjulia.com/examplelink';document.body.appendChild(tempInput);tempInput.select();document.execCommand('copy');document.body.removeChild(tempInput);}
Step 2 - Create the React component
The next step is to bundle this logic up into a React component and hook it to anonClick
event. I've called the functioncopyToClipboard
.
One thing to note is that I added a conditional check to first assess whether a user's browser even supports thecopy
command in the first place. This is done with thedocument.queryCommandSupported('copy')
statement. If it doesn't, this entire component would not work and thus should not render anything visible.
exportconstCopyTextIcon:React.FC=()=>{functioncopyToClipboard(){consttempInput=document.createElement('input');tempInput.value='https://bionicjulia.com/examplelink';document.body.appendChild(tempInput);tempInput.select();document.execCommand('copy');document.body.removeChild(tempInput);}return(<>{document.queryCommandSupported('copy')&&(<divid="copy-icon"onClick={()=>copyToClipboard()}className="cursor-pointer"><divclassName="mt-8 flex justify-center"><imgsrc={`${appConfig.publicUrl}/img/social/copy-mobile.svg`}alt="Copy"/><pclassName="ml-2 text-base-secondary text-sm light">Copy link</p></div></div>)}</>);};
Step 3 - Manage the copy text state
The next step was to manage the state of the "Copy link" text. To do this in React, I used theuseState
hook and coupled this with a timeout function within auseEffect
hook.
const[copySuccess,setCopySuccess]=useState('');useEffect(()=>{setTimeout(()=>setCopySuccess(''),2000);},[copySuccess]);
The other key step is tosetCopySuccess
state to'Copied'
upon theonClick
event.
functioncopyToClipboard(){consttempInput=document.createElement('input');tempInput.value='https://bionicjulia.com/examplelink';document.body.appendChild(tempInput);tempInput.select();document.execCommand('copy');document.body.removeChild(tempInput);setCopySuccess('Copied');}
To summarise what's happening here:
- The initial state of
copySuccess
is a blank string''
; - Upon clicking the button, the
copySuccess
state is set to'Copied'
; - The
useEffect
hook kicks in and resets thecopySuccess
state to a blank string''
after 2 seconds.
Step 4: Animate the text
Finally, we hook up the "Copy link" text and make it dependent on thecopySuccess
state, and then add some blinking animation (I've called the classblink
).
return(<>{document.queryCommandSupported('copy')&&(<divid="copy-icon"onClick={()=>copyToClipboard()}className="cursor-pointer"><divclassName="mt-8 flex justify-center"><imgsrc={`${appConfig.publicUrl}/img/social/copy-mobile.svg`}alt="Copy"/><pclassName="ml-2 text-base-secondary text-sm light">{copySuccess?(<spanclassName="blink">{copySuccess}</span>):('Copy link')}</p></div></div>)}</>);
Here's the simple CSS animation I created for the class.
.blink{animation:blinker1slinearinfinite;}@keyframesblinker{50%{opacity:0.2;}}
And that's it! No need for any external libraries. 🤓 Is there a better way of doing this? Let me know on Twitter@bionicjulia!
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse