Select box with placeholder in React


はじめに

こんにちは。kimizuy です。

今回は React を使ってプレースホルダー付きのシンプルなセレクトボックスの実装例を紹介します。

セレクトボックスでテキストフィールドのようなプレースホルダーを表現するには一工夫が必要だったので、本記事ではそこで得た知見を共有できたら幸いです。

1 つのファイルで管理したいという目的のみでスタイリングには styled-components を使っています。適宜、ご自身の環境に読みかえてください。

tldr

早速、コード例をご紹介します。

こだわりポイントは非クリック時のセレクトボックスの文字色です。

プレースホルダーのときはライトグレー、それ以外を選択しているときはブラックにして、有効/無効な値を選択しているかがわかるような見た目にしました。

CodeSandbox も用意しました。実際に触って挙動を確かめてみてください。

iimport styled from "styled-components";
import "./styles.css";

const StyledSelect = styled.select`
  width: 200px;
  height: 50px;
  background-color: white;
  &.-placeholder {
    color: lightgrey;
  }
`;

const StyledOption = styled.option`
  color: black;
  background-color: white;
`;

const Placeholder = styled.option`
  color: lightgrey;
  background-color: white;
`;

type Props = {
  options: { value: string; label: string }[];
} & React.SelectHTMLAttributes<HTMLSelectElement>;

const SelectBoxWithPlaceholder = ({
  options,
  placeholder,
  onChange,
  ...props
}: Props) => {
  return (
    <StyledSelect
      {...props}
      className={placeholder ? "-placeholder" : ""}
      onChange={(event) => {
        onChange?.(event);
        if (placeholder) {
          if (event.currentTarget.value) {
            event.currentTarget.classList.remove("-placeholder");
            return;
          }
          event.currentTarget.classList.add("-placeholder");
        }
      }}
    >
      {placeholder && (
        <Placeholder value="" selected>
          {placeholder}
        </Placeholder>
      )}
      {options.map(({ value, label }, i) => {
        return (
          <StyledOption key={value} value={value}>
            {label}
          </StyledOption>
        );
      })}
    </StyledSelect>
  );
};

const sample: Props["options"] = [
  { value: "foo", label: "foo" },
  { value: "bar", label: "bar" },
  { value: "baz", label: "baz" }
];

export default function App() {
  return (
    <div className="App">
      <SelectBoxWithPlaceholder
        options={sample}
        placeholder="選択してください"
      />
    </div>
  );
}

簡単な解説

onchange のイベントハンドラ内で -placeholder クラス(BEM でいうモディファイアクラスみたいなの)を値の有無に応じて追加したり削除したりしています。

例えば、値がある場合はプレースホルダー以外の選択肢が選ばれている状態なので、-placeholder を削除する、といった処理をしています。

これによってセレクトボックスの文字色を変更しています。

      onChange={(event) => {
        onChange?.(event);
        if (placeholder) {
          if (event.currentTarget.value) {
            event.currentTarget.classList.remove("-placeholder");
            return;
          }
          event.currentTarget.classList.add("-placeholder");
        }
      }}

おわりに

今回はプレースホルダーのあるセレクトボックスの実装例をご紹介しました。

<option> の見た目は OS やブラウザに大きく依存しているため、スタイルで融通が効きづらい点も覚えておくといいでしょう(参考)。

僕は最近まで知りませんでした。

以上、本記事が誰かのお役に立てれば幸いです。

弊社ではJamstackの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

投稿者 Gaji-Labo Staff

Gaji-Laboの社内デジタル環境でいろいろなお手伝いをしているがじ専務&じら常務。みんなのシリーズ記事をまとめたり、卒業したスタッフの過去記事を記録したり、Twitterをやったりしています。