input タグに入力された値をクリップボードにコピーする hooks と コンポーネントを作ってみたのでログとしてメモ
📝 Clipboard.writeText() を使ってクリップボードにテキストをコピーすることができる
clipboardjs のようなライブラリもあったのですが、ブラウザで動作するフロントエンドなら Clipboard API を使えばクリップボードに書き込みが可能そうだったのでライブラリなしに実装しました
Clipboard: writeText() method
ThewriteText()
method of theClipboard
interface writes the specified text to the system clipboard, returning aPromise
that is resolved once the system clipboard has been updated.
cf. Clipboard: writeText() method - Web APIs | MDN
const onCopy = async (text: string) => { try { await navigator.clipboard.writeText(text); } catch (error) { console.error(error.message); } }
Clipboard にテキストをコピーする hooks
// /hooks/useCopyClipboard.ts import { useCallback, useEffect, useState } from "react"; export const useCopyClipboard = () => { const [hasCopied, setHasCpied] = useState(false); const [error, setError] = useState<Error | null>(null); const onCopy = useCallback(async (text: string) => { try { await navigator.clipboard.writeText(text); setHasCpied(true); } catch (err) { if (err instanceof Error) { console.error(err.message); setError(err); return; } console.error(err); setError(new Error("Failed to copy")); } }, []); useEffect(() => { let timeoutId: number | null = null; if (hasCopied) { timeoutId = window.setTimeout(() => { setHasCpied(false); }, 1500); } return () => { if (timeoutId) { window.clearTimeout(timeoutId); } }; }, [hasCopied]); return { onCopy, hasCopied, isError: !!error, error, }; };
useCopyClipboard
hooks から返される onCopy
に渡した文字列をクリップボードにコピーするシンプルな hooks です (※ Chakra UI の useClipboard を参考にしました)
input に入力された文字列をクリップボードにコピーする
import { useRef } from "react"; import { useCopyClipboard } from "./hooks/useCopyClipboard"; export default function App() { const inputRef = useRef<HTMLInputElement>(null); const { onCopy, hasCopied, isError } = useCopyClipboard(); const handleCopyClipboard = () => { if (!inputRef.current) { return; } onCopy(inputRef.current.value); }; return ( <div className="App"> <input ref={inputRef} type="text" defaultValue="" /> <button type="button" onClick={handleCopyClipboard}> {hasCopied ? "Copied!" : "Copy!"} </button> {isError && <small className="text-error">Failed to copy<small>} </div> ); }
Sample
iframe だとクリップボードにコピーできないので codesandbox を直接開いてください
ライブラリを使うこと無くクリップボードに任意のテキストをコピーさせることができてびっくりしました!
と、同時に Clipboard API にはブラウザのサポートが完全なわけではないですがクリップボードから読み込みもあるので、evil なサイトではクリップボードの入力値を不正に API にも送るとか出来てしまうのかな〜なども気になるところでした。
evil な使い方が出来てしまうんので navigator.clipboard.readText
はサポートがマチマチなのかも?
おわり ₍ᐢ. ̫.ᐢ₎
[参考]