Laravel + React でプログレスバーをつくる

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、このところ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');

これは、LaravelReactをつなぐ役割をしてくれる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の開発ツールには送信スピードを変更する機能があります。これを使って送信スピードをゆっくりにして実行してみてください。(開発環境だと一気に送信できてしまうので確認しにくいためです)

では、実際の動画をご覧ください。(スピードは調整しています)

成功です😄✨

企業様へのご提案

今回のようにコンポーネントを多く作っておくと、開発が進むにつれて多くの「使いまわし」ができるようになります。

となると、開発スピードも上がるため作業効率が大幅にアップすることでしょう。

もしそういった開発をご希望でしたらぜひお問い合わせよりご相談ください。

お待ちしております。😄✨

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回は基本に戻ってLaravel + Reactでプログレスバーをつくってみました。

中身はTailwindを使っているので、今回のコンポーネントを改造して「大」「中」「小」サイズに切り替えられるようにしてもいいでしょうし、もっと装飾を追加するのも簡単にできるんじゃないでしょうか。

ぜひ皆さん独自のものをつくってみてくださいね。

ではでは〜❗

「窓の結露なくしたい…😫」

このエントリーをはてなブックマークに追加       follow us in feedly