カスタム選択コンポーネントを生成する


ハイフォークス.このブログでは、複合コンポーネントパターンを使用してカスタム選択コンポーネントを構築します.あなたが複合成分パターンであるかを知らないならば?そして、複合成分パターンはどのように見えますか?私のブログをチェックしてくださいcompound components .
ネイティブのHTML選択コンポーネントを使用していることを願っています.ネイティブの「選択」コンポーネントで、「select」と「オプション」の2つのコンポーネントが表示されます.両方のネイティブの選択コンポーネントを使用するために使用する必要があります.
<select>
 <option>One</option>
 <option>Two</option>
 <option>Three</option>
</select>
「選択」コンポーネントは、外部コンテナコンポーネントです.オプションは、「選択」コンポーネントのオプションを定義することです.ネイティブの選択コンポーネントは複合成分パターンを使用します.我々は選択したコンポーネントに同じパターンを使用するつもりです.
最初に選択を構築しましょう.Selectコンポーネントは、状態を保持するコンテナコンポーネントです.選択コンポーネントを構築するために必要な2つの主要な状態があります.
  • SelectedOption (現在選択されているオプションの値)
  • ShowDropDown(ドロップダウンリストを表示または非表示にするブール値).
  • import React, { ReactNode, useState, useRef } from "react";
    import useOnClickOutside from "../../hooks/useOnClickOutside";
    
    const Select: React.FC<{
      children: ReactNode | ReactNode[];
      defaultValue?: string;
      placeholder?: string;
    }> = ({ children, defaultValue, placeholder }) => {
      const [selectedOption, setSelectedOption] = useState(defaultValue || "");
      const [showDropdown, setShowDropdown] = useState(false);
      const showDropdownHandler = () => setShowDropdown(!showDropdown);
      const selectPlaceholder = placeholder || "Choose an option";
    
      const clickOutsideHandler = () => setShowDropdown(false);
    
     // custom hook to detect the click on the outside
      useOnClickOutside(selectContainerRef, clickOutsideHandler);
    
      const updateSelectedOption = (option: string) => {
        setSelectedOption(option);
        setShowDropdown(false);
      };
    
      return (
          <div className="select-container" ref={selectContainerRef}>
            <div
              className={showDropdown ? "selected-text active" : "selected-text"}
              onClick={showDropdownHandler}
            >
              {selectedOption.length > 0 ? selectedOption : selectPlaceholder}
            </div>
            <ul
              className={
                showDropdown
                  ? "select-options show-dropdown-options"
                  : "select-options hide-dropdown-options"
              }
            >
              {children}
            </ul>
          </div>
      );
    };
    
    export default Select;
    
    私はカスタムフックを使用していますuseOnClickOutside . このフックは、refとcallback関数を受け入れるリスナーのようです.指定されたrefの外でClickイベントが発生するたびにコールバック関数が呼び出されます.このカスタムフックを使用して、ユーザーが選択コンポーネントの外部をクリックしたときにドロップダウンリストを非表示にします.今度は、外側のコンポーネントを選択しました.次の手順は、オプションコンポーネントを構築することです.
    import React, { ReactNode } from "react";
    
    const Option: React.FC<{
      children: ReactNode | ReactNode[];
      value: string;
    }> = ({ children, value }) => {
      return (
        <li className="select-option">
          {children}
        </li>
      );
    };
    
    export default Option;
    
    オプションのコンポーネントが構築されます.困難な部分では、「オプション」コンポーネントの「選択」コンポーネントに存在するUpdateSelectedDopination関数を使用する必要があります.どのように、我々は選択とオプション構成要素の間で機能または状態を柱を通り抜けることなく共有しますか?

    チル、反応は小道具を通過せずにデータを共有する方法を提供し、これは反応の文脈が再生に来るところです.あなたが反応文脈に慣れていないならば、参照してくださいhttps://reactjs.org/docs/context.html .

    Context provides a way to pass data through the component tree without having to pass props down manually at every level.


    選択コンポーネントのコンテキストを記述しましょう.2つの値を共有します.selectedDoption & UpdateSelectedDoption.
    import { createContext, useContext } from "react";
    
    const SelectContext = createContext<{
      selectedOption: string;
      changeSelectedOption: (option: string) => void;
    }>({
      selectedOption: "",
      changeSelectedOption: (option: string) => {}
    });
    
    const useSelectContext = () => {
      const context = useContext(SelectContext);
      if (!context) {
        throw new Error("Error in creating the context");
      }
      return context;
    };
    
    export { useSelectContext, SelectContext };
    
    選択コンテキストを作成し、USElectContextはコンテキストを使用するカスタムフックです.ここで値をコンテキストに提供する必要があります.SelectContextを使用してコンテキストに値を提供できます.プロバイダー要素.
    // Select component
     <SelectContext.Provider
          value={{ selectedOption, changeSelectedOption: updateSelectedOption }}
        >
          <div className="select-container" ref={selectContainerRef}>
           ... 
           ...
          </div>
        </SelectContext.Provider>
    
    今、我々は文脈に値を提供しました.次の手順は、オプションコンポーネントの値を使用することです.USEelectContextを使用してコンテキストから値を取得できます.
    import React, { ReactNode } from "react";
    import { useSelectContext } from "./selectContext";
    
    const Option: React.FC<{
      children: ReactNode | ReactNode[];
      value: string;
    }> = ({ children, value }) => {
      const { changeSelectedOption } = useSelectContext();
    
      return (
        <li className="select-option" onClick={() => changeSelectedOption(value)}>
          {children}
        </li>
      );
    };
    
    export default Option;
    
    我々は今、オプション&選択コンポーネントを接続していた.オプションのいずれかをクリックすると、ChangeSelectedPopment関数がトリガされ、SelectedDeption状態が更新されます.また、選択したオプションを強調するために、オプションコンポーネントのコンテキストでselectedDopination値を使用することもできます.
    <Select>
         <Option value="one">One</Option>
         <Option value="two">Two</Option>
         <Option value="three">Three</Option>
         <Option value="four">Four</Option>
    </Select>
    
    歓声人々.ネイティブの選択コンポーネントと同じように動作する選択コンポーネントを構築しました.

    あなたは完全なコードを取得することができますcodesandbox . ハッピーコーディングフレンド.