【Typescript】Reactでテキストをコピーするボタンを実装する

スポンサーリンク

はじめに

TypescriptとReactでテキストをコピーするボタンの実装をしてみます。

CopyButtonの実装

クリップボードへのコピー部分に関しては下記のclipboard-copyを利用します。

clipboard-copy
Lightweightcopytoclipboardfortheweb.Latestversion:4.0.1,lastpublished:3yearsago.Startusingclipboard-copyinyourprojectbyrunning`npmiclipboard-copy`.Thereare272ot...

テキストをコピーするボタンの実装内容は下記の通りです。

"use client"
import copy from "clipboard-copy"
import { useState } from "react"

const CopyButton = ({ copyText }: { copyText: string }) => {
  const [isCopied, setIsCopied] = useState(false)

  const handleCopy = () => {
    copy(copyText).then(() => {
      setIsCopied(true)
      setTimeout(() => {
        setIsCopied(false)
      }, 3000)
    })
  }

  return (
    <button disabled={isCopied} onClick={handleCopy}>
      {isCopied ? "Copied!" : "Copy"}
    </button>
  )
}
export default CopyButton

isCopiedでコピーしたかどうかを判定して、コピーボタンに表示されたボタンをCopuからCopied!に変化させています。Copied!の文字は3秒(3000ミリ秒)後にCopyに戻るようになっています。

Next.jsで実装してみる

実際にNext.jsを使ってコピーボタンを実装してみます。

まずはNext.jsで新しいアプリケーションを作成します。

npx create-next-app@latest
Need to install the following packages:
  [email protected]
Ok to proceed? (y) y
✔ What is your project named? … copy-button
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias? … No / Yes

アプリケーションのディレクトリに移動して、clipboard-copyもインストールしておきます。

cd copy-button
npm install clipboard-copy

public配下のsvgファイルはいらないので削除してしまいます。

rm public/*.svg

CopyButton.tsxを配置するディレクトリを作成します。

mkdir src/components

CopyButton.tsxは下記の通りです。

"use client"
import copy from "clipboard-copy"
import { useState } from "react"

const CopyButton = ({ copyText }: { copyText: string }) => {
  const [isCopied, setIsCopied] = useState(false)

  const handleCopy = () => {
    copy(copyText).then(() => {
      setIsCopied(true)
      setTimeout(() => {
        setIsCopied(false)
      }, 3000)
    })
  }

  return (
    <button disabled={isCopied} onClick={handleCopy}>
      {isCopied ? "Copied!" : "Copy"}
    </button>
  )
}
export default CopyButton

src/app/page.tsxは余分なコードを削除して、下記のようにして試してみます。textListの文字列をそれぞれ表示して、コピーボタンでコピーできるようにしています。

import CopyButton from "../components/CopyButton"

export default function Home() {
  const textList: string[] = ["text1", "text2", "text3"]

  return (
    <div className="p-20">
      {textList.map((text, index) => (
        <span key={index} className="m-2">
          <div className="relative flex justify-between w-auto p-4 bg-gray-600 rounded-lg">
            <pre className="overflow-x-auto text-white py-2">{text}</pre>
            <CopyButton copyText={text} />
          </div>
        </span>
      ))}
    </div>
  )
}

準備ができたので、ローカルでアプリケーションを起動してみます。

npm run dev

localhost:3000にアクセスすると下記のようにコピーボタンがそれぞれ表示されていることが確認できます。

Copyをクリックすると、対象のテキストがクリップボードにコピーされて、ボタンがCopied!に変わっているのが確認できます。

参考

タイトルとURLをコピーしました