CloudFlareにデプロイするためのRemixプロジェクト 検索ボタンを1回実行されたら非活性にする

## 概要

Remixのプロジェクトにて検索ボタンを1回実行された非活性にする設定を付与する

## 前提

下記の内容が完了していること

https://qiita.com/miriwo/items/d143e5dd25ef54b47247

## 方法

1. 下記の様に`app/routes/_index.tsx`を修正して検索ボタンをタスク一覧画面が表示されるまで非活性に設定

    ```app/routes/_index.tsx
    import type { MetaFunction } from "@remix-run/cloudflare";
    import { useNavigate, useLoaderData } from "@remix-run/react";
    import { useState } from "react";
    import { loader } from "./task-category-masters-loader";
    export { loader };
    
    export const meta: MetaFunction = () => {
      return [
        { title: "Top" },
        {
          name: "description",
          content: "Top",
        },
      ];
    };
    
    export default function Index() {
      const navigate = useNavigate();
      const [isDeleted, setIsDeleted] = useState(false);
      const [isComplete, setIsComplete] = useState(false);
      const [taskCategoryMasterIds, setTaskCategoryMasterId] = useState<string[]>([]); // 初期値を空配列に設定
      const [isSearchButtonDisabled, setIsSearchButtonDisabled] = useState(false);
    
      const handleSearchClick = async () => {
        const queryParams = new URLSearchParams();
        if (isDeleted) {
          queryParams.append("isDeleted", isDeleted.toString());
        }
        if (isComplete) {
          queryParams.append("isComplete", isComplete.toString());
        }
        if (taskCategoryMasterIds.length >= 1) { // 配列の要素が1つ以上あるかで配列の中身をチェック
          taskCategoryMasterIds.map((taskCategoryMasterId) => {
            queryParams.append("taskCategoryMasterId", taskCategoryMasterId.toString());
          });
        }
        setIsSearchButtonDisabled(true);
        await navigate(`/tasks?${queryParams.toString()}`); // クエリパラメーターを含めて遷移
        setIsSearchButtonDisabled(false);
      };
    
      interface TaskCategoryMaster {
        id: string;
        name: string;
      }
    
      const taskCategoryMasters = useLoaderData<TaskCategoryMaster[]>();
    
      const handleCheckboxChange = (id: string) => {
        setTaskCategoryMasterId((prevIds) =>
          prevIds.includes(id)
            ? prevIds.filter((prevId) => prevId !== id)
            : [...prevIds, id]
        );
      };
    
      return (
        <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
          <div>
            <h2>タスク管理</h2>
            <div>
              <label>
                <input
                  type="checkbox"
                  checked={isDeleted}
                  onChange={(e) => setIsDeleted(e.target.checked)}
                />
                削除済みを表示
              </label>
            </div>
            <div>
              <label>
                <input
                  type="checkbox"
                  checked={isComplete}
                  onChange={(e) => setIsComplete(e.target.checked)}
                />
                完了済みを表示
              </label>
            </div>
            <div>
              <div>カテゴリ</div>
              {taskCategoryMasters.map((taskCategoryMaster: TaskCategoryMaster) => (
                <label key={taskCategoryMaster.id}>
                  <input
                    type="checkbox"
                    value={taskCategoryMaster.id}
                    checked={taskCategoryMasterIds.includes(taskCategoryMaster.id)}
                    onChange={() => handleCheckboxChange(taskCategoryMaster.id)}
                  />
                  {taskCategoryMaster.name}
                </label>
              ))}
            </div>
            <button
              onClick={handleSearchClick}
              disabled={isSearchButtonDisabled}
            >検索する</button>
          </div>
        </div>
      );
    }
    ```

1. `const [isSearchButtonDisabled, setIsSearchButtonDisabled] = useState(false);`でボタンの活性・非活性の状態管理をする変数を定義、検索ボタン押下時に検索ボタンのを非活性に設定し、画面が表示されたら活性状態にもどしている
1. 正常に検索ボタンをクリックして一覧に遷移できたら完了