【Typescript】Reactでテキストをコピーするボタンを実装する
はじめに
TypescriptとReactでテキストをコピーするボタンの実装をしてみます。
CopyButtonの実装
クリップボードへのコピー部分に関しては下記のclipboard-copy
を利用します。
clipboard-copy
Lightweight copy to clipboard for the web. Latest version: 4.0.1, last published: 4 years ago. Start using clipboard-copy in your project by running `npm i clipboard-copy`. There are 317 other projects in the npm registry using clipboard-copy.
テキストをコピーするボタンの実装内容は下記の通りです。
1"use client"
2import copy from "clipboard-copy"
3import { useState } from "react"
4
5const CopyButton = ({ copyText }: { copyText: string }) => {
6 const [isCopied, setIsCopied] = useState(false)
7
8 const handleCopy = () => {
9 copy(copyText).then(() => {
10 setIsCopied(true)
11 setTimeout(() => {
12 setIsCopied(false)
13 }, 3000)
14 })
15 }
16
17 return (
18 <button disabled={isCopied} onClick={handleCopy}>
19 {isCopied ? "Copied!" : "Copy"}
20 </button>
21 )
22}
23export default CopyButton
isCopied
でコピーしたかどうかを判定して、コピーボタンに表示されたボタンをCopu
からCopied!
に変化させています。Copied!
の文字は3秒(3000ミリ秒)後にCopy
に戻るようになっています。
Next.jsで実装してみる
実際にNext.jsを使ってコピーボタンを実装してみます。
まずはNext.jsで新しいアプリケーションを作成します。
1npx create-next-app@latest
1Need to install the following packages:
2 [email protected]
3Ok to proceed? (y) y
4✔ What is your project named? … copy-button
5✔ Would you like to use TypeScript? … No / Yes
6✔ Would you like to use ESLint? … No / Yes
7✔ Would you like to use Tailwind CSS? … No / Yes
8✔ Would you like to use `src/` directory? … No / Yes
9✔ Would you like to use App Router? (recommended) … No / Yes
10✔ Would you like to customize the default import alias? … No / Yes
アプリケーションのディレクトリに移動して、clipboard-copy
もインストールしておきます。
1cd copy-button
2npm install clipboard-copy
public配下のsvgファイルはいらないので削除してしまいます。
1rm public/*.svg
CopyButton.tsx
を配置するディレクトリを作成します。
1mkdir src/components
CopyButton.tsx
は下記の通りです。
1"use client"
2import copy from "clipboard-copy"
3import { useState } from "react"
4
5const CopyButton = ({ copyText }: { copyText: string }) => {
6 const [isCopied, setIsCopied] = useState(false)
7
8 const handleCopy = () => {
9 copy(copyText).then(() => {
10 setIsCopied(true)
11 setTimeout(() => {
12 setIsCopied(false)
13 }, 3000)
14 })
15 }
16
17 return (
18 <button disabled={isCopied} onClick={handleCopy}>
19 {isCopied ? "Copied!" : "Copy"}
20 </button>
21 )
22}
23export default CopyButton
src/app/page.tsx
は余分なコードを削除して、下記のようにして試してみます。textList
の文字列をそれぞれ表示して、コピーボタンでコピーできるようにしています。
1import CopyButton from "../components/CopyButton"
2
3export default function Home() {
4 const textList: string[] = ["text1", "text2", "text3"]
5
6 return (
7 <div className="p-20">
8 {textList.map((text, index) => (
9 <span key={index} className="m-2">
10 <div className="relative flex justify-between w-auto p-4 bg-gray-600 rounded-lg">
11 <pre className="overflow-x-auto text-white py-2">{text}</pre>
12 <CopyButton copyText={text} />
13 </div>
14 </span>
15 ))}
16 </div>
17 )
18}
準備ができたので、ローカルでアプリケーションを起動してみます。
1npm run dev
localhost:3000
にアクセスすると下記のようにコピーボタンがそれぞれ表示されていることが確認できます。
Copy
をクリックすると、対象のテキストがクリップボードにコピーされて、ボタンがCopied!
に変わっているのが確認できます。