
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、このところReact
を使ってちょっとだけディープな部分にフォーカスをしてきたのですが、このブログで追求してきた「シンプル + 強力」から少し外れてしまった感がありました。
そこで、今回は「React を使った基本的な開発」というテーマでお届けします。
そして、その具体的な内容は…
プログレスバーをつくる
です。
プログレスバーとは、以下のように「今どれだけ作業がしてる?」がパッと見でわかる表示のことですね。
ちなみに、このプログレスバーはTailwindCSS
を使ったものですが、今回はコンポーネント化して使いまわしがしやすいようにし、さらに色も自由に変更できるようにしてみましょう。
ぜひ何かの参考になりましたら嬉しいです。
「和歌山からふるさと納税の
有名クラフトビールが
届きました 」
開発環境: Laravel 9.x、React、Vite、Inertia.js、TailwindCSS
コントローラーをつくる
では、まずはLaravel
側のコントローラーから作っていきましょう。
以下のコマンドを実行してください。
php artisan make:controller ProgressBarController
すると、ファイルが作成されるので中身を以下のように変更します。
app/Http/Controllers/ProgressBarController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
class ProgressBarController extends Controller
{
public function create()
{
return Inertia::render('ProgressBar/Index');
}
public function store(Request $request)
{
return ['result' => true];
}
}
この中でやっていることは、以下のとおりです。
- create(): React で送信ページをつくる
- store(): データが送信される先。なお、今回はプログレスバーのテストですので、処理は何も入れていません。
ちなみに今回は基本的な内容でお届けしたいので以下部分のご紹介もしましょう。
return Inertia::render('ProgressBar/Index');
これは、Laravel
とReact
をつなぐ役割をしてくれるInertia.js
に「このページを表示してね」という設定をしています。
そして、その表示するためのファイルはresources/js/Pages/ProgressBar/Index.jsx
ということになります。(このファイル(ビュー)は後でつくります)
プログレスバーのコンポーネントをつくる
では、先ほどご紹介したビューの中で使うことになるコンポーネントを先につくっておきましょう。今回のメインになる部分ですね。
resources/js/Components/ProgressBar.jsx
export default function ProgressBar(props) {
const progress = props.progress || 0;
const additionalClassName = props.className || 'text-blue-100 bg-blue-600';
const className = 'text-xs font-medium text-center p-0.5 leading-none rounded-full '+ additionalClassName;
return (
<div className="w-full bg-gray-200 rounded-full">
<div
className={className}
style={{width: `${progress}%`}}> {progress}%
</div>
</div>
);
}
中身としてはシンプルに、progress
という値をセットすればプログレスバーが表示されるようになっています。
つまり、以下のようにセットした数字を少しずつ増やしていく流れになります。
<ProgressBar progress={progress}></ProgressBar>
また、className
をプロパティとしてセットすることができるので、もし色や大きさの変更がしたい場合は、以下のようにしてCSSクラスを追加することもできます。
<ProgressBar progress={progress} className="bg-green-600 text-green-50"></ProgressBar>
ビューをつくる
では、先ほどつくったコンポーネントを実際に使ってみましょう。
今回用意するのは3つのプログレスバーで、それぞれ「青」「緑」「黄色」で色分けをしています。
resources/js/Pages/ProgressBar/Index.jsx
import {useState} from "react";
import ProgressBar from "@/Components/ProgressBar";
export default function Index() {
// File
const [file, setFile] = useState(null);
const handleFileChange = e => {
const files = e.target.files;
if(files.length > 0) {
setFile(files[0]);
}
};
// Progress
const [progress, setProgress] = useState(0);
const handleSubmitProgress = e => {
const currentProgress = Math.floor((e.loaded * 100) / e.total); // プログレスバーの値を計算
setProgress(currentProgress);
};
// Submit
const [isSubmitting, setIsSubmitting] = useState(false);
const handleClick = () => {
setIsSubmitting(true);
let formData = new FormData();
formData.append('file', file);
const url = route('progress_bar.store');
const options = {
onUploadProgress: handleSubmitProgress
};
axios.post(url, formData, options)
.then(response => {
if(response.data.result === true) {
alert('完了しました!');
}
})
.catch(error => {
// ここでエラー処理
})
.finally(() => {
// setIsSubmitting(false); // テストのためコメントアウト
});
};
return (
<div className="p-5">
<div className="mb-5">
<input type="file" onChange={handleFileChange} />
</div>
<div className="mb-5">
<button
type="button"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
onClick={handleClick}>
送信する
</button>
</div>
<div className="mb-10">↓↓↓ ここにプログレスバーがでます</div>
{isSubmitting && (
<div className="w-96">
<div className="mb-7">
<ProgressBar progress={progress}></ProgressBar>
</div>
<div className="mb-7">
<ProgressBar progress={progress} className="bg-green-600 text-green-50"></ProgressBar>
</div>
<div className="mb-7">
<ProgressBar progress={progress} className="bg-yellow-500 text-yellow-50"></ProgressBar>
</div>
</div>
)}
</div>
);
}
この中で重要なのは、axios
のオプションにonUploadProgress
をセットしている部分です。
onUploadProgress
を使うと、送信途中でどれぐらい作業が完了しているかを計算することができ、それをやっているのがhandleSubmitProgress
になります。
ちなみに、今回はイメージしやすいようファイル送信ができるようにしていますが、この部分は必須ではありません。(テスト環境だと送信が早すぎて0%
と100%
しか確認できないことが多いのであえてつけています)
ルートをつくる
では、最後にルートです。
先ほどつくったコントローラーに対応しています。
routes/web.php
use App\Http\Controllers\ProgressBarController;
// 省略
Route::prefix('progress_bar')->controller(ProgressBarController::class)->group(function(){
Route::get('/create', 'create')->name('progress_bar.create');
Route::post('/', 'store')->name('progress_bar.store');
});
これで作業は完了です!
お疲れ様でした
テストしてみる
では、実際にテストしてみましょう!
まずはVite
を起動して「http://******/progress_bar/create」へアクセスします。
すると、以下のように表示されるので少し大きめのファイルを選択して送信してみましょう。
※ ちなみにGoogle Chrome
の開発ツールには送信スピードを変更する機能があります。これを使って送信スピードをゆっくりにして実行してみてください。(開発環境だと一気に送信できてしまうので確認しにくいためです)
では、実際の動画をご覧ください。(スピードは調整しています)
成功です
企業様へのご提案
今回のようにコンポーネントを多く作っておくと、開発が進むにつれて多くの「使いまわし」ができるようになります。
となると、開発スピードも上がるため作業効率が大幅にアップすることでしょう。
もしそういった開発をご希望でしたらぜひお問い合わせよりご相談ください。
お待ちしております。
おわりに
ということで、今回は基本に戻ってLaravel + React
でプログレスバーをつくってみました。
中身はTailwind
を使っているので、今回のコンポーネントを改造して「大」「中」「小」サイズに切り替えられるようにしてもいいでしょうし、もっと装飾を追加するのも簡単にできるんじゃないでしょうか。
ぜひ皆さん独自のものをつくってみてくださいね。
ではでは〜
「窓の結露なくしたい…
」