
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、React
が提供するHook
の便利さに触れて感動する毎日を送っています。(もしかすると、昔React
が使いにくいと感じたのはHook
がなかったからかもしれません)
そして、そうなると過去にVue
やjQuery
で作った機能もReact
でやってみたくなってきました。
そんなこともあって今回のテーマはこちら
クリップボードにコピーできるボタンをつくる
です。
機能としては「テキストをクリップボードにコピーし、貼り付けができるようにする」というものですが、こういった機能は便利ですよね。
ちなみに、我々開発者がよく見る場面でいうと、ウェブサービスの「APIキー」を取得するときが多いんじゃないでしょうか。
そこで
今回はLaravel + React
をつかって「クリップボードにコピーできるボタン」を実装してみたいと思います。
ぜひ何かの参考になりましたら嬉しいです。
「メモリ8 → 16 GB
でバク速PC環境に
もうnpm
は怖くない」
開発環境: Laravel 9.x、React、Vite、Inertia.js、TailwindCSS
ルートをつくる
では、まずはルートからです。
今回もひとつだけなのでコントローラーはつくらず、省略形で書いています。
routes/web.php
use Inertia\Inertia;
// 省略
Route::get('copy_to_clipboard', fn() => Inertia::render('CopyToClipboard/Index'));
ビューをつくる
そして、ブラウザで実際に表示される部分の「ビュー(テンプレート)」をつくります。
resources/js/Pages/CopyToClipboard/Index.jsx
import {useState} from 'react';
import CopyToClipboard from '@/Components/CopyToClipboard';
export default function Index() {
// Data
const [text1, setText1] = useState('ビール');
const [text2, setText2] = useState('ワイン');
const [text3, setText3] = useState('日本酒');
const texts = [text1, text2, text3];
// Methods
const handleClick = () => {
setText1('ラーメン');
setText2('カレー');
setText3('牛丼');
};
const handleCopy = text => {
console.log(`「${text}」がコピーされました`);
};
return (
<div className="p-5">
<h1 className="font-bold mb-5">【Laravel + React】クリックでクリップボードにコピーできるボタン</h1>
<small className="text-gray-500">コピー内容</small>
{texts.map((text, index) => (
<div key={index}>
{index+1}.{text}
</div>
))}
<div className="mt-3">
<a href="#" className="underline text-blue-700 text-sm" onClick={handleClick}>コピー内容を変更</a>
</div>
<hr className="my-5" />
{/* 基本 */}
<div className="mb-5">
<CopyToClipboard text={text1} onCopy={text => handleCopy(text)} />
</div>
{/* クラスを変更 */}
<div className="mb-5">
<CopyToClipboard
text={text2}
className="bg-red-500 text-white font-bold py-1.5 px-2.5 rounded-lg"
onCopy={text => handleCopy(text)}></CopyToClipboard>
</div>
{/* ラベルを変更 */}
<div className="mb-10">
<CopyToClipboard text={text3} onCopy={text => handleCopy(text)}>
<small>📋 クリップボードへコピー</small>
</CopyToClipboard>
</div>
<input type="text" placeholder="貼り付け確認用" />
</div>
);
}
なお、今回は以下のボタンを3つ作っています。(コンポーネントは共通のものです)
- 通常ボタン
- クラスを変更する(赤いボタンでよりカーブがきつい形)
- ボタンのラベル(テキスト)を変更し、絵文字も使う
コンポーネントをつくる
続いて、さっきの「ビュー」で使ったCopyToClipboard
コンポーネントをつくっていきます。
これが今回のメイン部分です。
resources/js/Components/CopyToClipboard.jsx
import {useState} from 'react';
export default function CopyToClipboard(props) {
// Data
const copyingText = props.text;
const buttonClassNames = props.className || 'bg-blue-500 text-white font-bold py-2 px-4 rounded';
const originalButtonLabel = props.children || 'コピーする';
const [buttonLabel, setButtonLabel] = useState(originalButtonLabel);
// Methods
const handleClick = () => {
navigator.clipboard.writeText(copyingText); // 注: https でしか使えません
setButtonLabel('完了!');
setTimeout(() => {
setButtonLabel(originalButtonLabel);
if(typeof props.onCopy ==='function') {
props.onCopy(copyingText);
}
}, 700);
};
return (
<button className={buttonClassNames} onClick={handleClick}>
{buttonLabel}
</button>
);
}
とてもコードとしては短いですよね。
今回は「こんなに短くても便利な機能が実装できるよ」というのを実感していただけたら嬉しいです
なお、中身としては「クリックされたらクリップボードへコピーする」だけなのですが、そのときにボタンのラベル(テキスト)を変更するためuseState()
を使っています。
ちなみに
もしhttp
でもコピーを実装したい場合は以下のページを参考にしてみてくだい。(題材はVue
ですが、コピー部分のロジックはまったく同じです)
テストしてみる
では、実際にテストしてみましょう(動画版は こちら)
まずVite
を起動し「https://******/copy_to_clipboard」へアクセスします。(コピーが必要なのでHTTPSでアクセスします)
3つのボタンの表示が違っています。
まずはうまくいっています
では、次に一番上の「コピーする」ボタンをクリックしてみます。
すると・・・・・・
ボタンのテキストが変わりましたので、以下の確認用入力ボックスに「Ctrl + V」で貼り付けてみましょう。
どうなるでしょうか。
はい
予定していたとおり「ビール」がクリップボードに保持されていました。
では、続いて「コピー内容を変更」リンクをクリックして、コピーする内容を変更してみます。
クリックすると・・・・・・??
はい、表示(変数の中身)が変わりました。
では、この状態で今度は赤のボタンをクリックしてみます。
以下のように完了ボタンが出て・・・・・
ペーストしてみると・・・・
はい
今回は表示変更後の2つめ「カレー」がコピペできました。
すべて成功です
デモページを用意しました
せっかくなのでデモページを用意しました。
ぜひ実際に触ってみてください
企業様へのご提案
今回のようにちょっと便利な機能をコンポーネント化しておくと、再度同じコードを書く必要がなくなり、開発を効率化することができます。
もしそういったご希望がございましたら、いつでもお気軽にご相談ください。
お待ちしております。
おわりに
ということで、今回はLaravel + React
で「クリップボードへコピーできるボタン」を作ってみました。
ちなみに今回はコピー機能を有効にするためにhttpsでブラウザからアクセスしましたが、そうなるとVite
の「オートリロード機能」が動かなくなってしまいました。(コンソールにもエラーが出ていました)
このあたりは今後調査し、何かわかりましたら後日追って報告したいと思います。
ではでは〜
「姪っ子がくれた
手紙に心から感動」