宿泊プラットフォームの再パッケージ-検索ページuseQuery Stringを使用して汎用ロジックを再使用

44616 ワード

前回の宣伝に続いて、再包装が完了した部分を整理しました.
このプロジェクトの核心的な機能は、様々な検索プロジェクトで希望する宿泊場所を検索することです.
私が担当している部分ではありませんが、大事なのでじっくり振り返ってみましたが、
プロジェクト終了後、既存のコードにクエリーの繰り返し入力などの問題があり、修正が必要です.
  • は、最初に再構築中に選択したフィルタ項目が維持できないという問題に遭遇し、この問題を解決するためにグローバルステータス管理を使用した.
  • 👉 どんな問題ですか。発生した問題とグローバル・ステータス管理を使用した理由の表示
  • 以降、この部分は残念ながらコードを再確認し、問題の原因を特定し、グローバルステータス管理がない場合に、クエリーのみを使用して素子内部で独立したステータス管理を行うために論理を変更した.
  • 👉 問題の原因は何ですか。トラブルシューティングプロセスの表示
  • および各形式についてcustom hookを用いて2つ以上の素子で繰り返し使用される論理を記述し、今日この部分をまとめた.
  • useQuery String Custom Hookの作成


    Custom Hookの使用を決定した理由は次のとおりです.
  • チェックボックスをリアルタイムで反映するには、再レンダリングのためにUSStateを使用してステータス管理を行う必要があります.
  • utils関数のみを使用すると、オブジェクトの状態を更新するための論理が繰り返され、コンポーネントのコードも長くなります.そこで、stateを管理するためにuseQuery StringObjectを単独で作成したいと考えています.オブジェクト値を変更する論理も関数になり、コードの再利用率を向上させることを目標としています.
    useQuery StringObjectは、状態をオブジェクトとして管理する必要がある場合に論理を含むカスタムフックです.
    人員と価格をそれぞれのkey、value形式で格納する必要がある場合に使用します.
    宿泊者宿泊料金count={  adult:0,  child:0,  baby:0,}priceRange = {  min:0,  max:0,}

    1. useQueryStringObject


    クエリーの値の管理


    デフォルトでは、URLSearchparamsを使用して現在のクエリーを受信する必要があり、前の値を再宣言する必要があるため、この部分を再使用しないようにcustom hook内部で定義されています.
    export const useQueryStringObject = (objKey, stateObj) => {
      const { search } = useLocation();
      const navigate = useNavigate();
      let URLSearch = new URLSearchParams(search);
      const [selectedListObject, setSelectedListObject] = useState(stateObj);

    ノーマルコンダクタンス関数


    オブジェクトの不変性を維持しながら一定の値を更新すると、類似の論理が繰り返され、コードの長さが長くなります.したがって、再使用するために関数として宣言します.
      const addFilterObject = (name, updatedResult) => {
        const updatedObject = {
          ...selectedListObject,
          [name]: updatedResult,
        };
        setSelectedListObject(updatedObject);
      };
    構成部品の内部での使用方法について

    宿泊者


    宿泊者を選択すると、countというキー値を使用してオブジェクトのキー値と値ごとに文字列が作成されます.
    例えば、成人1人と青少年2人を選択すれば、count=adult%D21&child=2となる.
    クエリー・リスト全体のキー値は「count」になるため、最初の再パラメータとして挿入されます.次に、2番目のパラメータを使用して、初期値になるオブジェクトを配置します.このオブジェクトを定義して入れないのは、初期値が空の場合、ユーザの増加に伴って数値が増加し、減算されるためです.値がNANに戻されないように初期値を定義します.
    export default function SelectPeople() {
      const initialState = {
        adult: 0,
        child: 0,
        baby: 0,
      };
      const { addFilterObject, selectedListObject, parseObjectToSearchParams } =
        useQueryStringObject('count', initialState);

    人員を増やす


    オブジェクトの状態を変更する論理は繰り返し続け、コードの長さが長くなるため、論理を分離して再使用します.
    userQuery StringObjectでは、addFilterObject関数がオブジェクトのキー値と変更する値またはコールバック関数を渡します.
    //useQueryStringObject.js
      const addFilterObject = (name, updatedResult) => {
        const updatedObject = {
          ...selectedListObject,
          [name]: updatedResult,
        };
        setSelectedListObject(updatedObject);
      };
    この論理を使用するコンポーネントは、以下の方法でコードを簡潔に記述してステータスを変更できます.
    //selectPeople.js
      const onClickPlusButton = name => {
        addFilterObject(name, selectedListObject[name] + 1);
      };
    
      const onClickMinusButton = name => {
        if (selectedListObject[name]) { // 인원이 0이상일 때만 감소
          addFilterObject(name, selectedListObject[name] - 1);
        }
      };

    宿泊料金


    価格は、最小値と最大値をキーとするオブジェクトでなければなりません.
    クエリのキー値はpriceRangeです.クエリを次のように管理します.priceRange=min%D22000&max%D228000
    export default function SelectPrice({ closeHandler }) {
      const initialState = {
        min: 0,
        max: 0,
      };
      const { addFilterObject, selectedListObject, parseObjectToSearchParams } =
        useQueryStringObject('priceRange', initialState);

    スライダバーを移動するたびに価格が更新されます


    同様に、スライドレバーを移動するたびに価格が更新されます.
    同様にaddFilterObject関数を使用しています.
      const handleChange = e => {
        const maxPrice = e.target.value * 10000;
        addFilterObject('max', maxPrice);
      };

    オブジェクトとクエリー変換関数


    オブジェクトをクエリーに変換する関数と、クエリーをオブジェクトに変換する2つの関数は、Custom Hookの内部で使用されます.

    オブジェクトをクエリーに変換

      const parseObjectToSearchParams = (
        obj = selectedListObject,
        page = 'list'
      ) => {
        let valueArr = [];
        Object.entries(obj).map(([key, value]) => {
          if (value) {
            valueArr.push(key + '=' + value);
          }
        });
        URLSearch.set(objKey, valueArr.join('&'));
        navigate(`/${page}?` + URLSearch.toString());
      };

    クエリーをオブジェクトに変換

      const parseQueryIntoObject = querystring => {
        const params = new URLSearchParams(querystring);
        const obj = {};
    
        for (const key of params.keys()) {
          if (params.getAll(key).length > 1) {
            obj[key] = params.getAll(key);
          } else {
            obj[key] = params.get(key);
          }
        }
    
        return obj;
      };
    これらの関数はどのように使用されますか?

    宿泊時間を選択した場合のクエリーの更新


    宿泊時間を設定するときは、開始日と終了日を選択するたびに、ライブラリを使用して定数値を更新します.このとき,ライブラリの特性上,各オブジェクトをオブジェクトで囲むことができず,各オブジェクトの臍の値を変えることもできず,無限ループに陥るという問題がある.
    一般オブジェクトを使用して、クエリー・リストからオブジェクトに変換し、値を更新してからクエリー・リストに変換して入力します.
    このときuserQuery StringObjectに含まれる関数ParseObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectObjectとParseQuery IntetoObjectを用いた.
      const { parseObjectToSearchParams, parseQueryIntoObject } =
        useQueryStringObject('dates', datesObj);
    
    
      useEffect(() => {
        const newDates = parseQueryIntoObject(dates);
      }, [location.search]);
      const handleDatesChange = ({ startDate, endDate }) => {
        const queryString = URLSearch.get('dates');
        const queryObject = parseQueryIntoObject(queryString);
          parseObjectToSearchParams(queryObject);
      };

    2. useQueryStringArr


    宿泊タイプと宿泊テーマは同じリストで構成されています.
    したがって,選択した項目を横並びに入れ,抜きながらチェックボックスの状態を管理するのが適切である.
    宿泊タイプ宿泊テーマ162選択タイプ=[「ホテル」選択テーマ=[[pool],[designToor]]

    宿泊タイプ

    export default function SelectType() {
      const {
        addFilterArr,
        handleCheckedAll,
        isCheckedAll,
        isChecked,
        parseArrayToSearchParams,
      } = useQueryStringArr('category');
    チェックボックスをクリックするたびに、選択した値が配列に追加されます.このとき、すでに配列で値を選択している場合は、配列から値を再削除し、存在しない場合にのみ値を追加します.
    //useQueryStringArr.js
      const addFilterArr = e => {
        let updatedList = [];
        const { name } = e.target;
        if (!selectedList.includes(name)) {
          updatedList = [...selectedList, name];
        } else {
          updatedList = [...selectedList].filter(cate => {
            return cate !== name;
          });
        }
        setSelectedList(updatedList);
      };
    チェックボックスischecked関数を使用して選択を反映し、チェックボックスをクリックするたびにhandleChange関数を実行します.
    //selectType.js
    {TYPE_DATA.category.map((item, idx) => {
      return (
        <input
          type="checkbox"
          checked={isChecked(item.name)}
          onChange={handleChange}
          />
    チェックボックスをクリックするたびにaddFilterArr関数を実行し、選択した値を配列に挿入または減算します.
    //selectType.js
      const handleChange = e => {
        addFilterArr(e);
      };

    選択/すべて選択

      const handleCheckedAll = () => {
        let updatedList = [];
    
        if (!isCheckedAll()) {
          TYPE_DATA[objKey].forEach(obj => {
            updatedList.push(obj.name);
          });
        }
    
        setSelectedList(updatedList);
      };
    
      const isCheckedAll = () => {
        return TYPE_DATA[objKey].every(obj => selectedList.includes(obj.name));
      };
    
      const isChecked = property => {
        return selectedList.includes(property);
      };

    選択内容を適用してクエリーに変換


    Custom Hookから渡されたキー値を適用し、更新された配列のキー値をクエリーに変換します.
    //useQueryStringArr.js
      const parseArrayToSearchParams = (page = 'list') => {
        URLSearch.set(objKey, selectedList.join('&'));
        navigate(`/${page}?` + URLSearch.toString());
      };
    構成部品では簡単に使用できます.
    //selectType.js
      const onClickApplyButton = () => {
        parseArrayToSearchParams();
      };

    宿泊テーマ


    同じタイプの検索項目なので、宿泊タイプと同じ検索項目を利用できます.
    export default function SelectTheme() {
      const {
        addFilterArr,
        handleCheckedAll,
        isCheckedAll,
        isChecked,
        parseArrayToSearchParams,
      } = useQueryStringArr('theme');
    
      const handleChange = e => {
        addFilterArr(e);
      };
    
      const onClickApplyButton = () => {
        parseArrayToSearchParams();
      };

    チェックボックス

                    <span>전체</span>
                    <input
                      type="checkbox"
                      value="space"
                      name="all"
                      checked={isCheckedAll()}
                      onChange={handleCheckedAll}
                    />
                  </label>
                </li>
                {TYPE_DATA.theme.map((obj, idx) => {
                  return (
                    <li key={idx}>
                        <input
                          type="checkbox"
                          checked={isChecked(obj.name)}
                          onChange={handleChange}
                        />
                      </label>

    3. useQueryString


    宿泊地区

    function SelectCity({ onToggle }) {
      const { selectedState, setSelectedState, parseStringToSearchParams } =
        useQueryString('city');
    
      function onClickSearch() {
        onToggle();
        parseStringToSearchParams();
      }
    
      return (
        <ModalSelectForm
          title="어디로 떠날까요?"
          onClickSearch={onClickSearch}
          onToggle={onToggle}
        >
          <Location
            selectedCity={selectedState}
            setSelectedCity={setSelectedState}
          />
        </ModalSelectForm>
      );
    }

    もっと考えたいこと。


    useQuery StringObject:クエリーをkeyとvalueに再パッケージ
    たとえば、上記のコードに従って再構築中にcheckin=2022-03-22&checkout=2022-03-25形式で追加されたクエリーが変更されました.dates=checkin%D2=2022-03-22&checkout%D22022-03-25のような形態を形成する.すなわち,dateという名前のキーでオブジェクトをクエリーリストに変換する文字列が再び囲まれる.
    これまで、再構築ロジックを使用して作成されたクエリーは、既存の問題を解決してきましたが、プロジェクトがバックエンドと交渉していた内容とは少し異なります.したがって、このロジックはクエリー管理に問題はありませんが、プロジェクト内部でapiを呼び出すときにエラーが発生します.
    では.どうしてこんなことになったの?
    クエリーを効率的に管理する方法を考える必要があるからです.直接やらないと触れられないところがあるので、一度やってみたいので、自分で比較してみます.
    現在はdates=checkin%D2=2022-03-22&checkout%D22022-03-25の形式でクエリーが生成されているが、バックエンドとの交渉の形式はcheckin=2022-03-22&checkout=2022-03-25である.企画で参考にしたSTAYPOLIOのホームページもこのように管理しているのかもしれないので、もう一度隠す必要はない、あるいはバックエンドapiリクエストに合った形がこれなので選んだのです.
    プロジェクト自体の完了度のために、既存のプロトコルのクエリーリストを変更し、バックエンドで前者のシェイプを処理できるかどうかを確認します.
    そしてもっと簡潔にCustom Hookを修正することができます!