🐈

Reactでライブラリを使用せずに、Styleを変えられるSelectBoxのComponentを作成する方法

2023/09/26に公開

こんにちは、AIQ株式会社のフロントエンドエンジニアのまさぴょんです!

今回は、Reactでライブラリを使用せずに、Styleを変えられるSelectBoxのComponentを作成する方法について解説します。

Styleを変えられるSelectBoxのComponentを作成する

学習がてら、Reactでライブラリを使用せずに、Styleを変えられるSelectBoxのComponentを作成してみました。

Defaultは、次のようなStyleのSelectBoxになっています。

今回作成したSelectBox Componentの作成の要点は、SampleCode中に記載していますが、まとめると、次のとおりです。

SelectBox Componentのポイントまとめ
  1. どんなoptionListがこちらに来るかは、idname以外は、あえて値はanyにして定義しない。
  2. CallBackのSetterは、anyのSetter(汎用性のために、あえて定義しない)方針で作成。
  3. wrapperStyleselectStyleは、CSS Object を受け入れて、存在する場合は、Setする。

SampleCodeは、次のとおりです。

CustomStyleSelectBox
import { CSSProperties, Dispatch, SetStateAction } from "react";

interface PropsType {
  /** NOTE: SelectBox の id => selectタグの外側で、labelタグを使用する際は、これを紐付ける */
  selectId: string;
  /**
   * NOTE: どんな OptionListがこちらに来るかは、
   * => id と name 以外は、あえて、any にして定義しない
   * => 汎用性のため
   */
  optionList: { id: number | string; name: string; [key: string]: any }[];
  /** NOTE: SelectBoxで Default表示する Value */
  defaultSelectVal: number | string;
  /** NOTE: any Setter => 汎用性のために、あえて定義しない */
  setter: Dispatch<SetStateAction<any>>;
  disabled?: boolean;
  wrapperStyle?: CSSProperties;
  selectStyle?: CSSProperties;
}

/**
 * NOTE: CustomStyleSelectBox
 * => Styleを Customize できる SelectBox Component を作成
 */
const CustomStyleSelectBox = (props: PropsType) => {
  const {
    selectId,
    optionList,
    defaultSelectVal,
    setter,
    disabled,
    wrapperStyle,
    selectStyle,
  } = props;

  /** Default の SelectBox Wrapper Style */
  const defaultSelectWrapper = {
    position: "relative",
    height: "20px",
  } as CSSProperties;

  /** Default の SelectBox Style */
  const defaultSelectStyle = {
    width: "200px",
    backgroundColor: "#EFEFEF",
    borderRadius: "8px",
    textAlign: "center",
    outline: "none",
    cursor: "pointer",
  } as CSSProperties;
  console.log("optionList", optionList);

  /** セレクトボックスの値が変更されたときに実行する関数 */
  const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    console.log(event.target.value);
    /** id を option_value に Set している */
    const id = event.target.value;
    /** 型を合わせた上で、select した target を find する */
    const targetOption = optionList.find((option) => option.id === Number(id));
    console.log("targetOption", targetOption);
    if (targetOption) {
      setter(targetOption);
    }
  };

  return (
    <div style={wrapperStyle ? wrapperStyle : defaultSelectWrapper}>
      <select
        id={selectId}
        onChange={(e) => handleSelectChange(e)}
        defaultValue={defaultSelectVal}
        style={selectStyle ? selectStyle : defaultSelectStyle}
        disabled={disabled}
      >
        {/* option タグでは、value が、option の 値になり、label が option の表示内容になる */}
        {optionList.map((option, idx) => (
          <option value={option.id} key={idx} label={option.name} />
        ))}
      </select>
    </div>
  );
};

export default CustomStyleSelectBox;

親Componentからの呼び出しは、次のような感じです。

Test.tsx
import { useState } from "react";
import CustomStyleSelectBox from "../ui-elements/selectbox/CustomStyleSelectBox";

const Test = () => {
  const optionList = [
    { id: 1, name: "ロボ玉", from: "グンマー帝国" },
    { id: 2, name: "まり玉", from: "さいたまー共和国" },
    { id: 3, name: "白桃さん", from: "東京都" },
    { id: 4, name: "ももちゃん", from: "ちばラギ県" },
  ];

  const initOption = optionList[0];
  type OptionType = typeof initOption;

  /** Sort Select Box の State */
  const [selectSortSetting, setSelectSortSetting] =
    useState<OptionType>(initOption);

  return (
    <div>
      <CustomStyleSelectBox
        selectId={"test-search-box"}
        optionList={optionList}
        defaultSelectVal={optionList[0].id}
        setter={setSelectSortSetting}
      />
    </div>
  );
};

export default Test;

まとめ

カスタマイズ性を考えながら、Componentを作成するのは、楽しいですね。

あえてany系が、それでいいのかは、有識者のご意見を伺いたいところです。。。

独自で、考えた実装なので、こういう実装の方がいいよ〜などアドバイスあったら、コメントいただきたいです。

個人で、Blogもやっています、よかったら見てみてください。

https://masanyon.com/

注意事項

この記事は、AIQ 株式会社の社員による個人の見解であり、所属する組織の公式見解ではありません。

求む、冒険者!

AIQ株式会社では、一緒に働いてくれるエンジニアを絶賛、募集しております🐱🐹✨

エンジニア視点での我が社のおすすめポイント

  1. フルリモート・フルフレックスの働きやすい環境!
    • 前の会社でアサインしてた現場は、フル出社だったので、ありがたすぎる。。。
    • もうフル出社には、戻れなくなります!
  2. 経験豊富なエンジニアの先輩方
    • 私は、3年目の駆け出しエンジニアなので、これが、かなりありがたいです!
  3. 自社開発とR&D(受託開発)を両方している会社なので、経験できる技術が多い。
    • 自社のProduct開発と、他社からの受託案件で、いろいろな技術を学ぶことができます。
  4. AI関連の最新の技術に触れられるチャンスが多い。
    • 自社で特許を持つほど、AI技術に強い会社で、プロファイリングを得意とした技術体系があります。
    • ChatGPTを自社アプリに搭載など、AIトレンドも、もちろん追っており、最新の技術に触れられるチャンスが多いです。
  5. たまに、札幌ラボ(東京から札幌) or 東京オフィス(札幌から東京)に出張で行ける!
    • 東京と、札幌に2拠点ある会社なので、会合などで集まる際に、出張で行けます。

採用技術 (一部抜粋)

  • FrontEnd: TypeScript, JavaScript, React.js, Vue.js, Next.js, Nuxt.js など
  • BackEnd: Node.js, Express,Python など
  • その他技術: Docker, AWS, Git, GitHub など

エントリー方法

  1. 私達と東京か札幌で一緒に働ける仲間を募集しています。
    詳しくは、Wantedly (https://www.wantedly.com/companies/aiqlab)を見てみてください。

Webエンジニア向け説明

https://www.wantedly.com/projects/1089410

データサイエンティスト向け説明

https://www.wantedly.com/projects/1089406

人事に直通(?)・ご紹介Plan(リファラル採用)

私経由で、ご紹介もできますので、興味のある方や気軽にどんな会社なのか知りたい方は、X(旧:Twitter)にて、DMを送ってくれても大丈夫です。
https://twitter.com/masanyon1212

AIQ Tech Blog (有志)

Discussion