Typed HooksGetting StarteduseClipboardCopy

useClipboardCopy

A custom React hook that provides clipboard copy functionality.

useClipboardCopy is a convenient custom React hook that enables copying text to the clipboard in React applications using the native JavaScript Clipboard API.

This hook handles browser compatibility checks and provides feedback on the success or failure of copy operations, making it easy to implement clipboard functionality with proper error handling. It also provides a status indicator that automatically resets after a delay.

Clipboard Copy Demo
Ready

API

useClipboardCopy(): [CopiedValue, CopyFunc, CopyStatus]

Returns

Returns [copiedText, copy, copyStatus]:

  • copiedText (string | null): The last successfully copied text or null if no copy has occurred or the last copy failed.
  • copy (function): A function that attempts to copy the provided text to the clipboard. Returns a Promise that resolves to a boolean indicating success or failure.
  • copyStatus ('idle' | 'success' | 'error'): The current status of the copy operation, automatically resets to 'idle' after 2 seconds.

Hook

import { useCallback, useState } from 'react'
 
type CopiedValue = string | null
type CopyFunc = (text: string) => Promise<boolean>
type CopyStatus = 'idle' | 'success' | 'error'
type UseClipboardCopyReturn = [CopiedValue, CopyFunc, CopyStatus]
 
/**
 * Custom hook to copy text to clipboard using the native JavaScript Clipboard API.
 * 
 * @returns An array containing the copied text, a function to copy text, and the current copy status.
 * 
 * @example
 * const [copiedText, copy, copyStatus] = useClipboardCopy();
 * copy("Hello, World!").then(success => {
 *   if (success) {
 *     console.log("Copied successfully!");
 *   } else {
 *     console.log("Copy failed.");
 *   }
 * });
 * copyStatus will be 'success' or 'error' based on the result
 * and will automatically reset to 'idle' after 2 seconds
 */
export function useClipboardCopy(): UseClipboardCopyReturn {
  const [copiedText, setCopiedText] = useState<CopiedValue>(null)
  const [copyStatus, setCopyStatus] = useState<CopyStatus>('idle')
 
  const copy: CopyFunc = useCallback(async (text) => {
    const stringText = typeof text === 'string' ? text : String(text)
    const { clipboard } = navigator
 
    if (!clipboard) {
      console.warn('Clipboard is not supported in this browser')
      setCopiedText(null)
      return false
    }
 
    if (!stringText) {
      console.warn('No text provided to copy')
      setCopiedText(null)
      return false
    }
    setCopyStatus('idle')
 
    try {
      await clipboard.writeText(stringText)
      setCopiedText(stringText)
      setCopyStatus('success')
      return true
    } catch (error) {
      console.warn('Copy failed', error)
      setCopiedText(null)
      setCopyStatus('error')
      return false
    }
  }, [])
 
  /** Reset copy status after a delay */
  setTimeout(() => {
    if (copyStatus === 'success' || copyStatus === 'error') {
      setCopyStatus('idle')
    }
  }, 2000)
 
  return [copiedText, copy, copyStatus]
}